For my final project, I wanted to render an animation of a dragon landing in an outdoor scene with a foggy environment. The key aspects of my objective were the rendering of the model itself, the modeling and rendering of the environment and the rendering of the fog. My secondary objective was to be able to render an animation of the dragon breathing fire.
My renderer is written in C++11. The design is inspired from the renderer Pbrt which offers a great flexibility in the integration of different rendering algorithms. The main features are described below.
The first rendering algorithm I implemented is Monte Carlo path tracing. It is a very powerful algorithm and it is quite simple. Thanks to path tracing, my renderer is able to render complex light effects such as diffuse inter-reflections and caustics. However, it produces noisy images and needs a lot of samples to give good results.
I also implemented Photon Mapping. It is a two-pass rendering algorithm presented by Henrik Jensen that produces significantly less noise in scenes where light comes mainly from indirect illumination (caustics and diffuse inter-reflections). I used this algorithm to render the UCSD Logo animation. However, I did not use it to render the dragon animation, as it there are no need for it in my outdoor scene (it is mainly direct-illuminated by the environment and a directional light).
In order to properly render the fog in my final scene, I had to implement the rendering of participating media. I used ray-marching to properly estimate absorption, emission, in-scattering and out-scattering in homogeneous and heterogeneous media. I only implemented single-scattering, so my renderer does not handle scattering of caustics light for example. However, it is sufficient for my scene and handles the volumetric shadows below the dragon that I wanted.
To add more realism to my final animation, I added motion blur and depth of field to my renderer. There are quite easy to implement and give nice results. Motion-blur was trickier as the dragon I used is a skinned mesh, so in each frame I had to store two versions of the whole model to interpolate it properly.
I implemented several materials. For glass materials I used fresnel equations together with snell's law to properly model the reflection and refraction of light. For other materials I mainly used Ashikhmin's BRDF, as it is highly customizable and is designed for Monte-Carlo rendering. To be able to render more realistic scenes, I used several kinds of textures such as color maps, specular maps and normal maps. I also used alpha maps to create objects that are limited by a texture such as tree leaves.
To enhance the lighting of my scenes, I implemented environment maps. It is also a quite simple feature that adds a lot of realism to a scene. I did no have the time to implement loading of HDR images so the lighting is not perfect but it stills gives a more realistic look to my scenes.
Creating the scene was quite challenging. The model I used is an animated dragon that I found on a website named TF3DM. It is very complete since it includes color textures but also normal and specular maps and even alpha maps for the holes in the wings. I set-up the scene using Maya. For the environment, I modeled a terrain and created textures in Photoshop. I also added a sphere-map for the sky. The model was already animated so I just had to animate the camera.
To be able to load my scenes and to easily configure all the parameters of my renderer, I implemented the loading of scene files. The format is pretty simple and is based on JSON so I used a third-party library to parse the files. Models are imported from several formats using two importers: the first used ASSIMP, a powerful library that loads a lot of 3D file formats. However, it did not handle all the features I needed and was not able to read FBX files, the main format used to export all the elements of a scene in Maya. So I integrated an FBX importer using FBX SDK. In order to be able to specify attributes specific to my renderer in imported scenes, I created a concept of "overrides" that allows to override specific elements of a scene such as materials or lights. The trickiest part was the loading and rendering of the skinned mesh for the dragon, but hopefully I attended CSE 169 - Computer Animation course last quarter so I managed to implement it.
Finally, I wanted to render fire. To be able to export simulation data from Maya, I wrote a Maya Plugin that exports grids of density and temperature for each frames of my animation.
The first render is directly based on my initial objective. It features the dragon arriving in a foggy scene and landing. It is rendered using Monte Carlo path tracing and volumetric rendering. I used Final Cut Pro to create the actual video from the rendered frames and applied some color corrections. The whole animation took about 10 hours to render on a i7 Quad-Core Macbook Pro.
The second render is an extension of the first objective with the addition of rendering of heterogeneous media. It features the same dragon as in the first video with this time a flame simulated in Maya and exported using my own plugin. It is rendered using Monte Carlo path tracing and volumetric rendering. The whole animation took about 5 hours to render on a i7 Quad-Core Macbook Pro.
Last but not least, I wanted to render an animation demonstrating photon mapping. I modeled this 3D version of UCSD Logo and simulated rigid body dynamics again using Maya. I used a environment map and depth of field to increase the realism of the scene. The whole animation took about 24 hours to render on a i7 Quad-Core Macbook Pro.