Ray Marching is a technique used for rendering 3D scenes in a screen. That means giving a color to each pixel.
Fragment shaders are a set of instructions executed by your GPU at once for every single pixel on your screen. Each instruction receive as input the position of the pixel and returns a vector representing the color the pixel will be showing.
In order to map the 2D canvas with a 3D scene, we introduce rays!
The main idea is that for each pixel of the screen, a ray is passing through it. All the rays starts from a viewport, so they have the same origin. And in order to recreate the scene, we define the trace (as we were walking through the ray) and see if we hit or miss an object in the scene.
This is a good analogy for understanding it.
Observe your computer and imagine that your eyes are emitting rays. Your mental perception of what you observing is in fact what I call canvas in the diagram. So the black cross (pixel) maps the red cross (computer).
The interesting part is the procedure of the algorithm. For identifying this "hits" it does not use an analytical method bewteen the ray and the objects in the scene. Instead it uses a distance estimator function that at each step along the ray identifies the nearest object until a fixed amount of steps, or until it reached some object which is close enough.
In this example:
At each step, you identify the minimal distance from the ray to all objects.
Go back to the ray, repeat procedure.
In 7 steps reaches near enough.
Code, code, code.
We will be using GLSL while exploring this example
Receives as input fragCoord that is a 2d vector with the position of each pixel.
After normalizing and postioning pixels, it is defined the camera origin (the viewport), the ray origin and the direction of the ray. Rotations are not necessary ( defined just to explore with transformations in a vector space).
fragColor is the output of the function and renders a 4d vector for each pixel representing RGB and alpha component. And as we said, the color is given by aplying the trace function from the rayOrigin in each direction.
Boundaries are set at the begining of the file.
#define MAX_STEPS 32#define MAX_DIST 10.#define SURF_DIST .001
For the trace, we start our walking at 0; if we did not reach the maximun steps we keep on walking through the ray and find de distance to the scene (ds). We stop if we are close enough to the surface, or if we walked enough.
vec3 trace(vec3 rayOrigin, vec3 dir) {float walk=0.;for(int i=0; i<MAX_STEPS; i++) {vec3 p = rayOrigin + dir*walk;float dS = scene(p);walk += dS;if(walk>MAX_DIST || dS<SURF_DIST) break;}return hsv2rgb(vec3((1.-walk)/1.9));}
I customize the function to return some colors.
You define your scene by using or combining the distance estimator primitives to create the objects in your scene.
The ModSpace is used for repeating shapes, in one or more dimensions.
Syntopia - Ray tracing and polygons