One of the big step was to implement Path tracing to add realistic global illumination to my renderer.
The image on the left is basic raytracing with only direct illumination and sampling on the area light. The image on the right is my path tracing implementation with 1000 samples by pixel. To load the 3D models, I use the Assimp library.
I implemented the absorption of light through an absorbing media. For this, I used the Beer–Lambert law.
On the left, the dragon has an absorbing media. It absorbs mainly red and blue, but also green. The tail of the dragon appears brighter because the ray runs through a shorter distance into the dragon.
The liquid into the glasses is a dielectric with absorption coefficients that make it look like whisky. I also added textures and an environment map (cubemap) to make the image more realistic.
Here are some images featuring some materials I used:
To have more details about the materials used, you can click on the images.
I also added alpha textures and normal mapping
I wanted to simulate the effect of light coming from a window which is scattered into dust particles. For this, I implemented both single and multiple scattering. A volume with multiple scattering takes a lot of time to render, because I throw a lot of new rays. But we can see some volumetric caustics with area lights that we don't see with single scattering. Later, I added heterogenous volume generated with a basic perlin noise. From this noise, I generate a density value for each point in the 3D space of the volume.
My final scene is lighted only by the light coming through the windows. Thus, path tracing is really bad and generates a lot of noise. Moreover, it doesn't handle caustics very well, especially for point lights. Therefore, I implemented photon mapping algorithm by Henrik Wann Jensen. I have been very careful to respect the light intensity and global illumination between path tracing and photon mapping. I generated a global map of photons for the global illuminations and a caustics map for the caustics.
I really want to see the effect of light dispersion through a diamond. Thus I first tried to implement dispersion by sampling one ray for red, green and blue randomly. It generates pretty good looking results. But I wanted to go further and I found this paper. The first image is a diamond without dispersion, the second is a basic sampling over red, green and blue, and for the third one I used the method describe in the paper.
It takes too much time to create a scene by hand. Thanks to the assimp library, I load .dae files that I create using Maya.
My first final image is an interior scene. A bedroom where the light comes from outside. I had to set all the materials to the scene. My first implementation of BVH was really bad with interior scenes. Thus, I implemented the surface area heuristic (SAH). It has divided my rendering time by 2.5. To avoid noise, I used photon mapping to render the scene. Then I added volumetric scattering to my photon mapping algorithm. More, to handle correctly the directional light coming from outside, I added a new type of light. This light reacts exactly like an area light except it emits photons only in one direction. Here are some images of the first versions.
Then I rendered two final images for the bedroom. They have both the same lighting but with a different point of view. The rendering time was about 20 hours for each image.