Jeremiah Darais
Subsurface Scattering
![]() | Phong Shading |
![]() |
With Scattering |
![]() |
Favor backward scattering |
![]() |
Favor forward scattering |
![]() |
Lambertian Shading on Spheres |
![]() |
With Scattering |
![]() |
Candlestick |
Details
Subsurface scattering accounts for materials that don't just interact with light at the surface, but allow the light to penetrate, scatter below the surface, and re-emerge elsewhere on the surface. My implementation uses path tracing to simulate subsurface scattering.
Currently, only homogeneous materials are supported. To support nonhomogeneous materials with this implementation, I would need to add in a way to approximate the shortest distance to the surface from a point inside the object.
The material takes a color term, a density, an index of refraction, a bias direction for scattering, a flag for computing direct light separately from path-traced lighting, and an exponent term for specular reflections if that flag is set.
Every time a light ray is scattered below the surface it's intensity is multiplied by the color of the material. Whether a ray interacts with the material below the surface is determined by the density. Determining how far a ray travels inside the object before scattering is similar to Beer's Attenuation. The density is the amount of light that gets scattered relative to the total amount of light, which is represented by dx/dt = -density*x where x is the amount of light, and t is the distance traveled. This yields the equation x = e^(-density*t), and by solving for t we can find the distance traveled given how much light has been scattered. Picking a random number between 0 and 1 for x will yield a random distance traveled by a light ray considering the probability that the ray will be scattered according to the density.
More complex light interactions occur on the surface. Many materials, like wax, have a thin, oily or plastic layer over the surface, resulting in reflectance on the surface. In my implementation, the material is given an index of refraction to use at the surface to calculate the Fresnel reflectance at the surface, and also to refract light rays penetrating the surface. When a light ray hits a surface, it is immediately scattered on the other side of the surface interface. I don't have much reasoning for this except that it drastically improved the appearance of the material. Before, I allowed the ray to penetrate the surface and continue in its refracted direction, but that resulted in some strange artifacts, like low-density materials actually becoming see-through, and very dark areas on surfaces where the reflectivity was high.
The subsurface scattering material I implemented can use path tracing for all lighting at the surface, or just for the indirect light. Because of the large amount of time for a path-traced image to converge, especially if the light source is small, I think the separate direct lighting calculation is sufficient, and looks good, though I have not tested how close the results of this method are to that of path tracing for all lighting.
Note: When I presented this project, someone pointed out the strange looking blue-ish streaks down the side of the candle. Those are the area lights that I used to give some ambient lighting to the scene, I just didn't realize that they would show up in the reflection off material I used for the candle. You can still see the effects of the subsurface scattering, though, since the candle itself is a neutral color, and the area light representing the flame is the only source of warm light in the scene.