Title: Port the Ray Tracer to GLSL Date: 2017-06-06T00:43:23 Tags: Recurse Center, Ray Tracer, GLSL Authors: Carl
Objective: Implement the path tracer in GLSL
In hope of improved performance and as an exercise in learning GLSL I attempted to implement the C Ray Tracer in GLSL.
There were two main challenges:
- GLSL does not support recursion.
- GLSL does not come with any built-in pseudo random number generator
Apparently due to lack of a stack in the GLSL architecture, recursive function calls are not permitted by the GLSL compiler.
In my original ray tracer implementation there was only one place where recursion
was being used: when a ray would hit an object
in the scene, the
color function would be called recursively using the hit point
as the origin for the bounced ray.
It turned out to be a bit tricky to figure out how to translate this recursive
call into an iterative one.
color function takes a ray and returns an RGB value. A ray is composed of
two 3 dimensional vectors, the origin of the ray, and the direction of the ray.
When the ray intersects with an object in the scene, that object contributes
to the RGB value that is returned. That contribution depends on the material of
the object, how much and what color it reflects and refracts.
The color value returned is a product of the color computed at each intersection.
Color can be seen as an accumulator, accumulating with each hit of an object.
Since the color value has only multiplication applied to it, order does not matter.
The first step was to create a local color variable - as previously this value was being
stored on the stack in the recursive implementation.
The next step was to create a loop that would stop either at a maximum number of
bounces of the ray, or on hitting an object where the ray stops.
It’s worth a mention here that because the rays start at the camera or eye, the path tracing approach sends rays in reverse to what occurs in nature where rays of light begin at the source of light and end at the camera or eye.
Regarding pseudo random number generation a popular approach is to use a
function that returns a number from a largely irregular sequence.
Typically a modulating function like sine is involved.
This PRNG function takes a seed value, whereas in the C implementation I’d
drand48 which does not. This involved some bug fixing on my part
to ensure that where the PRNG function was used that it was seeded with a
different value. As the PRNG returns the same value for the same seed.
With those resolved the remainder of the code was straight forward to write in GLSL. It’s especially nice to have built-in vector types complete with operator overloads.