File under: javascript, raymarcher, 3d, development, online

Javascript Ray Marcher v0.3

Here I have added lighting, giving a much softer render of the landscape. Diffuse lighting depends entirely on the angle of the light falling on the surface. If the light is off to one side and landing at a low angle, then the surface will receive less light. We assume the light is reflected in all directions, so we don't have to take the camera position into account, like we will do when we add specular lighting. Diffuse surfaces are typically soft materials like fabric, organic materials, dirt etc.

So the render process now works as follows:

In an analytic situation - tracing a sphere or other shape that has an algebraic solution to its surface - we could simply take the derivative of the surface to find the gradient. But we don't always know the formula for the surface - it could be a fractal surface, or a random cloud of points, or a density object that doesn't have edges, but rather fades out slowly at the edges. So how do we do it? The solution is simple in concept, but expensive in CPU terms.

To get the normal, we take the ray that has just hit the surface, rewind it one step, then fire two more rays into the surface, each one slightly off target. One of the new rays is shifted sideways a little, the other is shifted up a little. These two rays hit the surface, and the vectors from the original point to the two new rays form the basis for the surface and normal (or rather, for the gradient of the surface around the point), and their cross product is the normal vector that we want. This is an extension of the previous version, which assumed that there was only a ground function, so we could just request the height of the ground at any point. However our secondary rays could be going upwards or sideways. We can even calculate the gradient at the point where two onjects touch, by firing secondary rays into both objects.

In the picture below, the bands of colour on the front hills, are actually a mistake in the colouring algorithm. Initally I thought it was just an issue with the step size that would dissapear when I optimsed the speed and reduced the step size, but in fact it is a fundamental problem in my implementation. I'm leaving it there as a demonstration of...something inportant, I guess.

{{% thumbnail src="/projects/javascriptraymarcher/ver3.png" caption="An early render, almost correct" scale="30" %}}