Heterogeneous Participating Media (30pts)
Homogeneous Medium
Implementation
Added files:
medium.h
medium.cpp
homogeneous.cpp
volpath_mats.cpp
For the implementation of media, I closely followed the approach described in PBRv3. For this, I first had to add an interface medium.h
that
all media have to be a subclass of. This interface specifies all methods a medium implementation has to offer, the most important ones being
Sample()
and Tr()
, where the first one is responsible for sampling the free path inside a medium and returning an importance weight and
the second one to compute the transmittance between two points inside the medium.
Both methods use the formulas described in the lecture but additionally support spectrally varying extinction coefficients, by uniformly sampling the wavelength to use
for the distance sampling.
By adding a Medium
member to the ray, I ensure that the ray can keep track of the medium it is currently inside of. Its Medium
member
gets initially set by the camera, to which one can attach a medium via the xml, and later gets updated whenever the ray intersects with a mesh.
For this purpose, up to two mediums can be attached to a mesh in the xml, one for inside the mesh and one for outside the mesh. Then, if the ray
continues to the inside of the mesh, ray.medium
will be updated with the medium on the inside, otherwise with the medium on the outside of the mesh.
Having medias as children of shapes also allows them to be placed anywhere inside the scene by just placing the respective mesh. If one would like to have a pure
medium boundary, the bsdf for the mesh can be omitted, so the mesh no longer represents a light scattering surface.
Lastly, I also had to add a new integrator volpath_mats.cpp
that supports participating media. It is really similar to the path_mats.cpp
integrator but additionally checks in each loop iteration, whether the ray is in a medium and if so, it samples a free path by calling the Sample()
method from the medium. This will update the throughput by the returned importance weight and if a medium interaction is sampled, the integrator
will sample the phase function for a new direction, otherwise it will handle the intersection with a light scattering surface the same way as
path_mats.cpp
with the additional change that it will skip over null bsdfs (i.e. pure medium boundaries).
I also added support for the environment map emitters that were implemented by Michael.
Some other modifications to the existing code are additions of convenience methods and / or members to the Intersection
, common.cpp
and scene.h
.
Particularly for scene.h
, I added an IntersectTr()
method, that returns whether a ray intersecting with a light scattering surface
and the transmittance up to that point.
The xml syntax for specifying a medium is the following (it's similar for cameras, except that you can only specify one medium there):
...
...
Validation
I validated my implementation by comparing with Mitsuba as well as varying some medium parameters. One of the meshes used is the Stanford Bunny. Since mitsuba uses a MIS integrator, I use a lot higher samples per pixels for my images and the noise generally looks worse. However, for some scenes, Mitsuba has a lot more fireflies than my implementation.
Stanford Bunny




Nested Media


Colored Spheres with and without dielectric bsdf




Additional Result (Attaching a medium to a camera)


Heterogeneous Medium
Implementation
Added files:
heterogeneous.cpp
volumegrid.h
volumegrid.cpp
For the heterogeneous medium, I closely followed the PBRv3 implementation again. This means that also the heterogeneous medium must implement the
medium.h
interface. Here, for the Sample()
method, I use Delta Tracking as described in the lecture slides
and for the Tr()
method, I use Ratio Tracking. However, in the case of heterogeneous media, I do not allow for a spectrally varying extinction coefficient anymore
(The absorption and scattering coefficient may still be spectrally varying though as long as their sum is uniform over all spectra).
To model the spatially varying extinction coefficient of heterogeneous media, I decided to use the .vol file format
that is also used by Mitsuba. This is convenient as this format is relatively simple but I can easily obtain data as Mitsuba provides a .vdb to .vol file converter.
To parse the .vol files, I implemented the volumegrid.cpp
class. In the constructor, this class parses the .vol file specified in the xml. It offers a key method Density()
that for a given point p returns the density of the extinction coefficient at p. The density gets
trilinearly interpolated in case p doesn't lie exactly on the voxel grid. The return value of Density()
is used by the Delta Tracking and Ratio Tracking algorithms to scale the baseline extinction
coefficient passed to the medium in the xml. One key challenge here is that the point passed to the Density()
method must be in the medium coordinate system. I solve this
by first mapping the mesh that places the medium in the scene to a centered unit cube and then mapping this unit cube to the medium bounding box.
Adding heterogeneous media to the scene can be done analogeously as for homogeneous media - attaching them as children of a mesh object or a camera. But this time, the mesh associated with the medium should be a centered unit cube that was placed in the scene by a series of translations, rotations and scalings. The integrator is exactly the same as for homogeneous media.
The xml syntax for specifying a heterogeneous medium is almost the same as for a homogeneous one, but it additionally takes a filename as
a parameter:
Validation
I validated my implementation by comparing with Mitsuba as well as varying some medium parameters. I obtained the .vol files by using the converter offered by mitsuba to convert vdb files which can for example be obtained from here. Since mitsuba uses a MIS integrator, I use a lot higher samples per pixels for my images and the noise generally looks worse. However, for scenes with high(er) scattering, Mitsuba has a lot more fireflies than my implementation.
Bunny Cloud Scattering


Bunny Cloud Absorption


Additional Results ($\sigma_s=100$, $\sigma_a=10$ vs. $\sigma_s=150$, $\sigma_a=50$)

