In this post, we are going to cover the code to make reflect in ray marching. Reflections in rastertization are normally handled by a bunch of different tricks, including multiple draw-calls, in this article, I will foccus on a ray marcher, using only two triangles and a pixel shader.
Let’s start with our very simple main function, as a pixel shader. I won’t go over how the ray marching works on here, as it as been previously covered on my blog, and it’s a pretty much widely known technique.
We are going to work with 5 iterations, in those iterations let’s do these simple algorithms.
- Trace the ray from origin and direction
- Check if the ray hits something
- If hits, compute the reflective vector from hitpoint normal worldspace with ray origin.
- If so, compute the new ray origin to be the hitpoint and the direction to be the reflective vector.
Alright, let’s dive into code, and start to implement those simple rules!
For this tutorial, I will work with 2 simple sphere, place in different place in the worldspace.
So our Map function looks something like this:
I will simply add this line, so this way our 2 spheres will be black.
Alright, from this point, we can easily start to work on our reflective algorithms we defined earlier.
The first thing we need is to defined some stuff from the point we hit. First we will need the position in worldspace from this point: We we can simply compute using the good old formula:
Or here simpler form:
p(t) = A + t*B
A: ray origin,
B: Ray direction
This function gives us a very handy way to compute any point t on the ray.
So recall you want the point that the hitpoint occured, in our code, we could simply use this following like of code.
giving us, just like expected: The position in worldspace. I simply assigned the colored of the hit as the position worldspace of the hit.
Alright, next stuff, normal worldspace:
note: I will go a bit over this subject as computing normal in worlspace using raymarching algorithms can be a bit of a whole subject on its own, so just assume we have this worldspace we just computed and we want to calculate the normal of this point.
Let’s just use our calcNormal functions:
Giving us this:
Next task is to compute the reflection vector from the ray direction with the normal of the surface we hit. Here is how reflection works on a diagram, you check the incident ray, in our example it’s the ray direction, and the normal we just created.
There would be a way to manually make a function that compute that Reflected ray, but GLSL has a built in function that handles that just for us, so let’s add this to our code!
Giving us that:
Alright, we almost getting there: Next step will be to use what we have just computed to actually setup a new ray origin to compute what our tracing sees from that point.
Step one: to setup the new ray origin, we simply call the pos worldspace and add the normal worldspace to it.
Then we set the ray direction to be reflected vector we have just created.
So here, we can see 5 levels of reflection, as we map the color inside the render loop to be querying 5 times the castRay function, for every iteration we apply the reflection so the output color giving us this:
Let’s add some computation of color for every reflections we just had computed.
Inside the hitpoint from the loop, we simply define a color, and this color will be computed from the reflection based hitpoint we just computed.
Let’s simply define a color, without any further computation, and simply use what we have calculated before to shade the scene properly.
Giving us this boring image:
Adding an ambiant color:
Giving us this:
Let’s add diffuse, so we can actually see a bit of processing from our reflections things: We make a simple dot product from the normalized light pos, and normalized normal worldspace.
Then it gives us that!
Well, this is some very basic reflections in ray marching!
You can add the ambiant lighting, so we have a more colorfull scene to work with!
So now, if we add those two together, we have an nice thing going on, color and lighting!
Let’s animate that scene!
Very boring static shit going on here, so what about we animate one of your sphere to see it real time? Yeah, let’s do that:
So here I simply change the sphere 1 position (the one on the right in our scene) to move from -2 to 2 on the y and z axis.
For multiple animations:
We could tweak the position of the light, add another sphere and so on! Just have fun!
Tweak the light sources, the 3rd sphere and so on: using the same patterns to animate and make the scene dynamic, we could also change color!
Here is the complete code of the shader 🙂