= Final Project: Lava / Molten Material = == Project Goal == == Implementation == * Black Body Illumination A true black body is an ideal diffuse radiator -- it emits light and absorbs all incoming light. Although most materials are not true black bodies, lava and other molten metals do emit an approximate black body spectrum. The black body power distribution function at each wavelength is specified completely by the temperature of the material. Therefore, to determine the emitted light from a point on a surface of a given temperature, we integrated the product of the black body power distribution function and the XYZ response functions over the visible spectrum to end up with an XYZ color representation of the spectrum. This XYZ color was converted to RGB for use as the emitted light of an area light. * Procedural Texturing for Temperature Lookup: * Surface Shading: As mentioned above, a black body radiator absorbs all incoming light. However, no materials are ideal black body radiators; as lava cools it becomes reflective. Looking at our reference images, we saw a broad specular highlight on the lava, which had cooled to a rather bumpy surface. We decided to approximate this appearance by using a Blinn microfacet distribution with a high degree of roughness and a bump map. However, we wanted to correlate the reflectivity of the surface with the temperature -- high temperatures would be less reflective -- so we provided configuration parameters for smoothly transitioning the weight of the BSDF. == Final Images == == Challenges / Interesting Investigations == * Color representation of black body spectrum: Our initial implementation of the black body code had a bug which made the emitted power far far too low for what PBRT was expecting. This led to a wide range of investigations trying to find out what techniques were used for color representation of black body radiation. First, there are many black body radiation color-temperature gradients on the web. Here is an example: However, these gradients are created by "self-normalizing" the color returned by the black body spectrum integration -- divide each of the XYZ color values by the sum of the XYZ values for a particular color. This means that you can represent the colors nicely, but it does not represent the intensity of the color properly at all. The emitted power of a black body increases as temperature^4^, so higher temperatures are orders of magnitude brighter than lower temperature, and the color gradients do not represent this. For instance, 1500K should be bright yellow, but the color gradients expect it to be orange. The paper "Physically Based Modeling and Animation of Fire" by Nguyen, Fedkiw, Jensen called uses the black body radiation method as well, and then uses a von Kries transform to approximate chromatic adaptation. They assume that the fire in their scene is the primary illuminant, and use the von Kries transform to scale all colors to the color of the maximum temperature. This has the effect of saturating the color of the maximum temperature to white, which might be an okay idea for fire; but it does not apply well to lava or molten metal. For instance, we wanted to be able to represent metal at 800 kelvin, which should be a dark red. If this was the only illuminant in the scene, adapting to it would force it to white, which is really not correct. The paper "Extending the Photon Mapping Method for Realistic Rendering of Hot Gaseous Fluids" by Kang, Ihm, and Bajaj, does two interesting tricks with the black body spectrum: * 1. if they are looking for a particular color, they compute the temperature for which the maximum intensity is at a wavelength near that particular color, and then run their simulation at that temperature * 2. additionally, they allow artists to specify the range of wavelengths over which to evaluate the black body radiation, which biases the resulting color. We chose not to apply either of these techniques because we wanted to base our results off a reasonable temperature for the materials we were looking at, instead of choosing a color and matching it. As it turned out, our black body code just had one of the constants off by scale factor (m^2^ instead of nm^2^), which threw off the whole computation when it was divided by wavelength^5^. Going over the code in detail found this error and made the resulting Le in the right range and color. * SPARKLES! For a long time during development, we would get a number of VERY VERY bright pixels. We noticed that this problem was especially bad at the intersection of a light shape with a non-light-shape, although sometimes they would appear on the surface of the light shape itself. It turned out that the distance between the shading point and the light emitting point was so small that the PDF returned by the light was very close to 0 (but not quite zero), and was causing the returned radiance to be super high. We worked around this by changing the PDF computation to ignore rays where the distance squared was too near to zero and would cause these horrible sparkles. == Future work == * Importance Sampling the area light source: One of the challenges of our project was that we needed a lot of samples of the light source in order to get an image with low variance -- and we had several scenes where we wanted multiple large light sources. The Area Light Source implementation in PBRT assumes that the light source will emit light uniformly across its area, so it samples the shape uniformly by area in Sample_L -- choosing larger polygons more often in proportion to their areas. Because our light source does not emit light uniformly by area, we wanted to sample according to a different distribution that would be preferential to triangles which emitted more power (even if they were small). Although we were able to change the sampling to choose a polygon more often in proportion to its power, we were unable to derive the transformation from a uniform-by-power distribution to a non-uniform-by-area distribution in order to convert to the required form for PBRTs weighting. It would be nice to complete this work. == References ==