Raymarching!

Wherein rays are traversed in search of a function's value

The idea

I stumbled upon the tutorial/article [1] and wondered if I could recreate some of the images.

The raymarching technique is similar to raytracing, but differs in how intersections are found.

The general idea is that for each ray, we "march" along the ray until the height of a point on the ray is smaller than some function y=f(x, z).

The Terrain

Perlin Noise

To use randomness to control parameters in a smooth or more controllable way, simply using random() wouldn't work, since it's too random and discontinuous.

Ken Perlin created a noise function that is continuous and with a controllable frequency. [3] By taking random gradients at lattice point and bi-linear interpolating between them, a smooth function emerges.

I adopted a gradient noise function from Texturing & Modeling: A procedural Approach, and here's one result.

The noise function takes 3 parameters (x, y, z) and returns one float value. This means it's 3 dimensional, but we only need a planar slice of it.

Here's the function for x,y about 0 to 30 and a fixed z.

Perlin noise

Fractal Noise

Using the noise function, we can create a "fractal" by summing noise functions of different frequencies, and attenuated amplitudes. If each successive frequency is double the previous, it's called an "octave" similar to a musical scale.

This is a fractal in a sense that we're repeating a pattern at different scales.

Also called Fractional Brownian Motion, this has 3 octaves

Shading the terrain

When a ray intersects, I colored the point depending on the height and normal. The normal is calculated using 4 really close points as shown in [1].

I interpolated from brown to grey based on the height, and if the normal's y component is bigger than 0.9, I color it green.

The sky is just an image I index to (after scaling) if the ray doesn't intersect.

Here's a render with 5 octaves:

This one is with 7 octaves:

This one has snow.

Rendering with octaves from 2 to 8

Bugs encountered

At one point in testing the fractal noise, I noticed these discontinuities

They happened at all x,z < 0, so I just pointed the camera elsewhere. The smooth-looking green area on the right is actually the area of interest. I multiplied the function by 10 to make the curves more pronounced.

Usage

To compile:

make terrain

to run:

./terrain 320 430 light.pov [octaves. default is 5]

light.pov is needed since I used my raytracer as a base code and it reads the light information from it.

Code

I will put my code on my github.

References

[1] terrain raymarching

[2] more terrain marching

   * didn't use much but was informative

[3] David S. Ebert, et al. Texturing & Modeling: A procedural Approach 3ed.

   * helped me understand how noise function and noise fractals work. Has whole chapters on them.

Background Image: http://www.flickr.com/photos/cubagallery/5599620163/