POV-Ray : Newsgroups : povray.off-topic : WebGL : Re: WebGL Server Time
27 Jul 2024 22:27:32 EDT (-0400)
  Re: WebGL  
From: Orchid Win7 v1
Date: 9 Jun 2016 14:46:06
Message: <5759b96e$1@news.povray.org>
On 09/06/2016 06:53 PM, Orchid Win7 v1 wrote:
> On 09/06/2016 08:11 AM, scott wrote:
>>> After about an hour of squinting at the sparse ShaderToy documentation
>>> and making some educated guesses, I did eventually manage to build a
>>> trivial ray-tracer that runs in real-time.
>>
>> Come on, make it public and post the link then for all to see :-)
>
> I'm sure you've all seen a white sphere with some coloured lights. :-P

OK, here ya go:

struct Ray
{
     vec3 S, D;
};

vec3 RayPoint(in Ray ray, in float t)
{
     return ray.S + ray.D*t;
}

Ray Camera(in vec2 uv)
{
     Ray ray;
     ray.S = vec3(0, 0, -5);
     ray.D = vec3(uv.x, uv.y, 1);
     return ray;
}

struct Sphere
{
     vec3 C;
     float R;
     float R2;
};

Sphere MakeSphere(vec3 center, float radius)
{
     return Sphere(center, radius, radius*radius);
}

float IsectSphere(in Ray ray, in Sphere sphere)
{
     // (P - C)^2 = r^2
     // (P - C)^2 - r^2 = 0
     // ((Dt + S) - C)^2 - r^2 = 0
     // (Dt + S - C)^2 - r^2 = 0
     // (Dt + V)^2 - r^2 = 0
     // D^2 t^2 + 2DVt + V^2 - r^2 = 0

     vec3 V = ray.S - sphere.C;
     float a = dot(ray.D, ray.D);
     float b = 2.0*dot(V, ray.D);
     float c = dot(V, V) - sphere.R2;

     float det = b*b - 4.0*a*c;
     if (det >= 0.0)
     {
         return (0.0 - b - sqrt(det))/(2.0*a);
     }
     else
     {
         return -1.0;
     }
}

float Illuminate(vec3 light, vec3 surface, vec3 normal)
{
     vec3 d = light - surface;
     return dot(normalize(d), normalize(normal));
}

vec2 MapScreen(vec2 xy)
{
     return (xy - iResolution.xy/2.0) / iResolution.y;
}

vec2 MapScreenExact(vec2 xy)
{
     return (xy - iResolution.xy/2.0) / iResolution.xy;
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
     Sphere s1 = MakeSphere(vec3(MapScreenExact(iMouse.xy)*4.0, 0), 1.0);

     vec3 l1 = vec3(-5, +5, -3); // Red
     vec3 l2 = vec3(+5, +5, -3); // Green
     vec3 l3 = vec3( 0, -5, -3); // Blue

     Ray cr = Camera(MapScreen(fragCoord.xy));
     float t = IsectSphere(cr, s1);

     if (t > 0.0)
     {
         vec3 surface = RayPoint(cr, t);
         vec3 normal = surface - s1.C;
         float b1 = Illuminate(l1, surface, normal);
         float b2 = Illuminate(l2, surface, normal);
         float b3 = Illuminate(l3, surface, normal);
         fragColor = vec4(b1, b2, b3, 1);
     }
     else
     {
         fragColor = vec4(0, 0, 0, 0);
     }
}

Copy & paste into the ShaderToy website and hit Go. You can click on the 
image to move the sphere around. (It doesn't follow your cursor exactly 
because of the perspective transformation.)


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.