I have tried to follow the code from his book as much as possible, but I had to make some changes to get it running in a fragment shader:
- There are no classes (and methods) in glsl so I use structs and functions instead. Inheritance is implemented by adding a type variable to the struct and adding ugly if/else statements to the (not so overloaded) functions.
- The scene description is procedurally implemented in the world_hit function to save memory.
- The colour function is implemented using a loop because it is not possible to have a recursive function call in glsl.
- Only one sample per pixel per frame is calculated. Samples of all frames are added in Buffer A and averaged in the Image tab.
Besides that, I also made some other design choices. Most notably:
- In my code ray.direction is always a unit vector so I could clean up the rest of the code by removing some implicit normalizations.
- Cosine weighted hemisphere sampling is used for the Lambertian material.
Please run the shaders below (using the play button on mouseover) for some time to see it converge to the final image.
Chapter 6: Rectangles and lights
You can find (the full source of) the fragment shader on Shadertoy: https://www.shadertoy.com/view/4tGcWD.
Chapter 7: Instances
You can find this shader here: https://www.shadertoy.com/view/XlGcWD.
Chapter 8: Volumes
You can find this shader here: https://www.shadertoy.com/view/XtyyDD.
I really like how a constant medium starts to look more and more like a solid object with a Lambertian surface for increasing density.
Chapter 9: A Scene Testing All New Features
And finally, this shader can be found here: https://www.shadertoy.com/view/MtycDD.
If you like this post, you may also like one of my other posts:
- Raytracing in one weekend
- Old watch: a WebGL path tracer
- Ray Tracing – Primitives
- Image-Based Lighting
- Human Document