Mysterious mushroom in orange planet and curious creatures!
Click on the image to get the higher resolution image (1280x720).
My idea for the final rendering was to setup a scene in a foreign planet on a orangy surface, where some creatures are approaching an abstract mushroom like object (which probably came from another planet!). Among the creature there is a dragon flying in and an earth elemental monster. My objective was to implement some area lighting effect with ambient occlusion with different shading effects with each object present in the scene. For the terrain I used a produral texture pattern combined with the base texture and it also have some distance based attenuation with the background image to simulate an atmospheric effect on the horizon. The dragon model uses its own base textures whiel the earth elemental model has a procedurally generated 3D texture to give it a dirty, earthy and scary look.
Rendering Configuration:
Modeling the Scene:
The scene uses wavefront obj models for the terrain, dragon, mushroom and earth elemental model and a rectangle for the
background. I choose 16:9 aspect ratio for the scene so that it seems expanded in the sides. The models combine a total
of 305,860 triangles that makes the scene quite complex and time consuming to render with a decent number of samples.
I had to implement some transformation and scaling functions in my matrix class to place and orient the objects properly in the scene.
I did some hacking in the obj model import functions to replace the textures and surface types to control shading on different
objects. The acceleration data structure (binary kd-tree) that I had implemented earlier proved to be vital for such a scene,
and obviously improvements in that area would definietly save more rendering time.
Lighting:
I implemented Area Lights with Ambient Occlusion, and I used a Disk geometry for the primary light source in the
scene. The Disk light was sampled with a uniform distribution and the hemispheres at each hit point used to approximate
ambient occlusion was sampled with a cosign distribution. The effect of ambient occlusion is apparantly visible especially
undeneath the objects on the terrain, and in the mushroom model. However, the soft shadows are unfortunately not
very apparant because the light source is quite far away.
Texturing:
The terrain used a special Texture object that would weight its base texture color (provided with the object model file)
with a procedurally generated texture pattern to give it a grainy and not-so-smooth look. I tried to choose the color
so that it appears a little orangy to match the background and the look-and-feel of a mars like planet (with a different texture however).
To simulate some atmospheric attenuation effect on the terrain in the horizon I have added a color with each point by
sampling a color from the background from the hit point and weighting it based on the distance from the hit point to
the background (approximated). This gives a really nice distance based attenuation effect in the horizon.
I also used similar procedural texturing on the earth elemental model with different colors and parameters to give it a
dirty, earthy and scary look. I implemented a marble based produral texture class using 3D perlin noise for this purpose.
For the background I choose a large rectangle and positioned it behind the objects in the scene. This background is sampled
by the texture used in the terrain to simulate distance based attenuation.
The dragon model uses regular uv coordinates generated in the source model file and provided texture.
Sampling and Anti-aliasing:
I used the Jittered samples for distributing rays on pixels, and also in sampling light sources and the environment.
However, because of area lighting and ambient occlusion I needed to use a lot of samples to reduce the noisy patterns in the image.
Initially I used a single set of samples for each pixel or each geometry. This gave a repeatitive aliasing after a certain distance.
So I modified my implementation to generate multiple sets of samples and jump to a randomly choosen set after one set
of samples are exhausted. This gave much better results. But still if I used more samples per pixel I would get much better
rendering quality and less noise in the final image.
Post Processing:
I have used floating point color values that are unbounded by any max values. After all the rays has been traced, I normalized
the color (rgb) values by the maximum of r, g, b computed and then I used a log(1 + color) tone mapping for all the pixels.
For the final project I had to add many components to my ray tracer. It was a great learning experience to improve my
sampling patterns, redesign code for area lighting and implement perlin noise based procedural shadering. Also I did some
additional effects such as distance based attenuation and improve my texturing support to add realism to the scene.
The complexity of the scene was also dependent upon the large triangle meshes that I used, they used a total of
305,860 triangles. The total rendering took 3 hours and 11 minutes to render, thankfully because of the acceleration data
structure was used for each model. Choosing intensities and radiance values for lights and surfaces was proved to be
a challenge for me, sometimes it was difficult to find the right intensity and color combintations and to control them
the way I wanted.
For improvements I could think of working more on area lighting models and to use
even better sampling patterns. There were a few things in my wish list that I could not implement due to time constraints, that
the dragon was supposed to carry a fireball in its legs (procedurally hypertextured). And I wanted to use a better surface
shader for the mushroom model as well.
*** The source code for the ray tracer: reLib