Participating media

It's been a while, but I'm back with a render that's crazy delicious. I've recently looked into rendering of participating media like fog and smoke, and applied this to my ray tracer. Currently I've implemented constant density fog and fog that's inverse exponential with respect to height. The fog density affects scattering, where photons bounce off fog particles and continue to travel in other directions, and absorption, where photons are absorbed by a fog particle. To simulate this I use an exponential probability distribution to compute the distance until the next scattering and absorption events for a given ray. If the distance is less than the distance until the ray hits an object the ray is scattered or absorbed depending on the lower distance. Here's the result:


Atmospheric scattering

This weekend I got around to implementing the atmospheric scattering approach described in "A Practical Analytic Model for Daylight". It is basically a simplified model of the scattering that happens when light travels through air, with the light from the object being out-scattered, and sunlight and skylight being in-scattered. The amount of scattering is determined by the amount of turbidity in the air. Higher turbidity leads to higher haziness or cloudiness in the air. The result can be shown in the following renders, the first one with low turbidity and the two last ones with high turbidity:

A Practical Analytic Model for Daylight


Beer's Law

I added Beer's law causing light that travels through water to be attenuated based on the inverse exponential of the distance traveled. This means that increasing depth will give the water a darker appearance, as seen in the render below:

I also switched to an implicit representation of the water surface, reducing the memory requirements. In addition I compute the normal vector based on the water surface equation instead of indirectly based on the height map, meaning the water surface is now bump mapped, and the geometrical resolution doesn't need to be that high in order to get high frequency details in the light reflection and refraction.



I made a simple height map generator which basically just sums a set of sine curves with different directions, amplitudes, and wavelengths, creating something that looks like water. The amplitude of the waves are also modulated by the water depth by looking at the height of the terrain when computing the water height map, so that the waves will get more shallow closer to shore. Combining the water height map with Fresnel based reflection and refraction produces the nice water effect shown in the image below:

The height map for the water now takes up the same amount of memory as the terrain height map, so I might try to avoid storing it explicitly, instead computing the sum of sines on demand. This also requires some changes to the kd-tree I use for ray tracing a height map, storing the tree nodes there implicitly as well. The upshot is that the highest wave frequency would no longer be limited by the resolution of the height map.

Reflections & Refractions in Raytracing


Depth of field and Perlin noise

This weekend I added depth of field to the ray tracer. Basically it involves perturbing each camera ray slightly based on a lens radius and a focal distance. It doesn't require a lot of code to add it to a working path tracer, and the result is pretty nice:

I also added Perlin noise and created a procedural marble-like texture for the statues:


Just for fun

Just for fun I did a render where the only light sources in the scene are the Lucy statues. With ray tracing this is really simple, I just set the emissive term of the material used for the model to some value, and render the scene using path tracing. The result was kind of cool so I decided to share it:


Albedo correction

Someone commented that the lighting was a bit off in the previous render, and it turns out the albedo was too low on both the statue and terrain. I increased the terrain's albedo to be closer to the 0.25 of green grass, and set the statue's albedo to 0.5. This made the render look a lot more natural and removed the hard shadows:

Note: I lowered the height of the statues a bit to make the scene less crowded (there are still 36 million statues). The increased amount of indirect lighting caused more noise, so for this render I used 2000 samples per pixel giving a render time of 9 hours.