The BRDF Zoo: Blinn-Phong, Phong, and Torrance-Sparrow BRDFs

This assignment requires implementations of various BRDFs. While they seem straightforward at first, it requires careful planning. And, there are still subtleties that need to be taken care of.
In the implementation, I first created a BRDF class which has the parameters the BRDF id, the exponent, and a pure virtual function for calculation of the BRDF itself. Then, each BRDF is derived from this base class, implementing the BRDF calculation and adding other parameters as needed.

The original Blinn-Phong model was the one that we were using so far. One can debug this scene by comparing it with the renders without the BRDF functionality. Blinn-Phong model relies on half vectors for specular highlights:



The modified Blinn-Phong model relies on half vectors as well, and it is quite straightforward. I used an if-else block for normalization and exposed this as a field in Modified Blinn-Phong class:



The normalized version includes adjustments to be energy-conserving. Here's how it looks:


Here are the Killeroo scenes with Blinn-Phong BRDF:






The Phong model differs from the Blinn-Phong, mostly because Phong uses the reflection vector, instead of the half vector:



The distribution of the specular highlight is quite different from Phong BRDF. The modified version of Phong BRDF uses modified formulation, just like its Blinn-Phong counterpart.



The Modified Phong BRDF also has a normalization feature, to be energy-conserving. It is similar to the Modified Blinn-Phong BRDF's normalization scheme, where formulation changes:


Torrance-Sparrow Model is the most involved of all. Some corner cases need to be handled, which I will be discussing shortly. The terms of the Torrance-Sparrow BRDF, such as the D distribution function, G function, and the Fresnel factor, requires great care to get them right. To calculate the fresnel factor, I used the method for the conductor materials that I have implemented for earlier assignments. The scenes did not indicate whether the material was conductor or dielectric, so I find the conductor assumption to be working. For the diffuse component, if kdFresnel was true, there was a multiplier of (1 - fresnel factor) for the diffuse component. Here are the renders for the Torrance-Sparrow model:






For both Blinn-Phong and Torrance-Sparrow Killeroo scenes, the results are tonemapped with the global operator. An observation is that the Torrance-Sparrow model, without any normalization, looks similar to the energy-conservation version of the Blinn-Phong model.

Discussion

Short-circuiting the return statements reduce nesting. However, it is easy to overlook what the code is supposed to accomplish in the first place. I did such short-circuiting with returning the color in case of a shadow hit success when I was first implementing the BRDF. The result was the scene is actually working with one light, and code "seems" right. It was quite hard to figure out since perceptually one can tell there is a specular component missing. When I figured out that short-circuit, the scene was rendered as expected. Here's how it looks when it short-circuits. Clearly, a specular highlight is missing here. The significant part is how to interpret this:



During the implementation, the back-face culling changed the way scenes look for the Killeroo scene. Here's such an image:



It is clear that, to the left of the image, some of the triangles had unintended intersections, resulting in oddly-looking shadow patches.

When I first implemented the Torrance-Sparrow model, the render was like this:


It is all white, with some black pixels, resembling the Killeroo model. The debugging process went like this: After I saw this image (PNG), I took a look at the EXR output. It seemed okay at first. Then, I opened the EXR output in bracket and applied tonemapping in bracket. Here's how it looked in bracket:



There were black pixels at the boundaries of the model. Using the pixel info on these black pixels, I figured out that they were not black:


The value was #IND. So, the global operator could not tonemap the image with #IND values, resulting in mostly white pixels. When I singled out and debugged those individual pixels, I saw that the cos(phi) term, which is in the denominator of the specular component of the Torrance-Sparrow model, is 0 at those pixels. I used the expression "cosPhi = max(dot(wo, hit.normal), 0.0f);", in a rote fashion, influenced from the earlier calculations with cos(theta). Then, for such edge cases, I returned pure black, and the problem is resolved. I also tried using abs(cosPhi) but saw no perceptual difference in the image. Using abs of cosPhi seems not so physically correct, so I stick with the first approach. Having a tonemapping operator that can work locally turned out to be quite handy to detect such cases.

Another thing that is worth mentioning is about the degamma feature in the raytracer: In my implementation, I have applied the degamma transform only to the ambient, diffuse, and specular components of the materials. So, I did not apply the degamma transform to the absorption and refraction indices.

The rendering times for Killeroo scenes were around 15 seconds. The spheres were rendered instantly.

Comments