Diff for "CurtisAndrus/FinalProject"

Differences between revisions 15 and 16

Deletions are marked like this. Additions are marked like this.
Line 80: Line 80:
Finally, here is the plate of watermelon that I did not have time to render for the competition:[[BR]]

attachment:final.jpg [[BR]]

Final Project Writeup

Group Members: Curtis Andrus


The goal of my project was to produce realistic images of watermelons. The original proposal can be found here: CurtisAndrus/FinalProjectProposal.

Techniques Implemented

The scattering of light within the watermelon was simulated using volumetric photon mapping, and the structure of the watermelon was simulated using a cellular texture function.

Volumetric Photon Mapping

Simulation of single-scattering light in the watermelon was done using standard volume rendering (already implemented in PBRT). Multiple scattering was done using photon mapping, by tracing photons through the volume and storing them in a volumetric photon map.

Movement of the photons in the volume is determined using ray marching. At each point p encountered in the ray marching process, the probability that the photon will interact with the volume at p is given by 1 - exp(-int(sigma_t(x),x = p0->p)), where p0 is the point where the photon entered the volume [1]. If a photon leaves the watermelon without interacting with the volume it is not stored in the photon map. If it does interact, sigma_s(p)/sigma_t(p) is the probability that the photon will scattered at point p. If it is scattered a new direction is computed by importance sampling the phase function. Also, the radiance of the scattered photon is scaled by the scattering probability. If the photon is not scattered, it is absorbed and stored in the photon map.

The watermelon is rendered using ray-marching to compute the single-scattering term. At each point, the multiple scattering contribution is computed by adding of the radiances of each photon. This formula for this is given by the following equation:

step_size * Sum(phase(x,wp,w)*photon_radiance/((4/3)*pi*r^3), p=1->N)

Where phase() is the phase function of the volume, and r is the radius of the sphere in which the photons are located [2]. The phase function I used consisted of a linear combination of two Henyey-Greenstein phase functions, one for front-scattering and one for back-scattering. The weights of each term are user parameters, and my scenes generally had a larger weight for front-scattering.

I implemented the photon mapping by adding a volumetric map to PBRT's photon map integrator. I created a new "subsurface" material plugin that associates a VolumeRegion object with a shape, so that I could specify volumes inside shapes. If a photon hits a surface with a volume, it is then traced through the volume and stored in a separate map using the method described. The estimate of the volume radiance is computed by adding the term to the value computed by PBRT's single scattering volume integrator.

Photon Mapping Test Images:

A test of the watermelon model, using a Perlin noise as the density function.

A backlit slice of watermelon. The image on the right is rendered with photon mapping, while the image on the left is rendered without.

Cellular Texturing

To simulate the internal structure of the watermelon, I implemented the noise function described in [3] based on the idea of randomly placed feature points. Each volume has an associated set feature points, and the density of the volume at each point p is determined by p's distance to the nearest 3 feature points (In [3] it was determined that using points beyond the 4 nearest did not give noticeable differences). The exact formula I used for computing the density at a given point is the following:

density(x) = 0.5*|0.6*D3 - D2 + 2.0*D1|

The Dn are the distances to the n-th nearest feature point. The maximum allowed density is 1.

At each point, the absorption cross section and the scattering coefficient at each point in the watermelon are computed by multiplying a user-provided parameter by the density computed by this function. The set of feature points is stored in the kd-tree data structure built into pbrt. This allowed me to take advantage of the Lookup() method, which is used to find the photons within a certain distance.

Cellular Texture Images:

This image was rendered without photon mapping, and the effect of the texture can be seen in the slices. I was relatively pleased with this texture since the dark "spots" in the texture look like places where seeds could have been in the watermelon.

These images demonstrate the texture and the photon mapping effects. The image on the right was rendered with the photon mapping, so light can be seen on the sides of the watermelon where it is not directly illuminated by the light (the light in this scene is directly above).

Scene and Modeling

I modeled the watermelon slice and plate in Maya and exported them to the OBJ format, then used the Wavefront shape plugin (from http://www.cs.ucf.edu/~colbert/mayapbrt/goodies.php) for PBRT to render the models.

Technical Challenges

The biggest issue I had was getting the parameters right. If the scattering coefficients are slightly off the watermelon will look too gray or even look like it's glowing. Every time I changed the code the color parameters in my scenes needed to be adjusted to get the right look. Before the competition I had thought I found the right parameters to give the appearance of watermelon, but I corrected a few bugs and that threw the colors off, which resulted in my final image not looking like watermelon.

I also attempted to simulate how the color of a watermelon changes near the outside, and set the density function to change to a smoothly constant value at some distance from a user-provided watermelon center point. This can be seen in the first example of the cellular texture, and in the following image:

In the end I also had issues finding a satisfactory color for this portion of the watermelon, so I turned it off for the final image. I had also modified PBRT's marble texture to serve as a skin texture, but I was unable to get the texture coordinates imported correctly from Maya, so I chose not to use that as well.


I had initially intended my final scene to be a plate full of watermelon slices, but long render times prevented me from creating that. Instead, I submitted this image to the competition:

I was slightly disappointed with this image, as it did not properly reproduce the watermelon-like appearance I was going for, but of the images I considered submitting I think it was the best. Here is another image I considered, but I decided against it because I thought the outer edge area looked like rock:

Here is a larger version of the final scene, with parameters slightly altered:

Finally, here is the plate of watermelon that I did not have time to render for the competition:

Source Code & PBRT Scenes

Source Code: source.zip
PBRT Scenes: scenes.zip

The watermelon.pbrt contains a single watermelon slice rendered for the final image, and final.pbrt contains the plate of watermelon slices that I was unable to render in time for the competition.


[1] Julie Dorsey, Alan Edelman, Henrik Wann Jensen, Justin Legakis and Hans Kohling Pederson: "Modeling and Rendering of Weathered Stone" (Proceedings of SIGGRAPH'99).

[2] Realistic Image Synthesis Using Photon Mapping by Henrik Wann Jensen.

[3] Steven Worley: "A Cellular Texture Basis Function".