Production Volume Rendering SIGGRAPH 2017 Course: Julian Fong, Magnus Wrenninge, Christopher Kulla, Ralf Habel
Production Volume Rendering SIGGRAPH 2017 Course: Julian Fong, Magnus Wrenninge, Christopher Kulla, Ralf Habel
With significant advances in techniques, along with increasing computational power, path tracing has now become
the predominant rendering method used in movie production. Thanks to these advances, volume rendering can now
take full advantage of the path tracing revolution, allowing the creation of photoreal images that would not have
been feasible only a few years ago. However, volume rendering also provides its own set of unique challenges that
can be daunting to path tracer developers and researchers accustomed to dealing only with surfaces. While recent
texts and materials have covered some of these challenges, to the best of our knowledge none have comprehensively
done so, especially when confronted with the complexity and scale demands required by production. For example,
the last volume rendering course at SIGGRAPH in 2011 discussed ray marching and precomputed lighting and
shadowing, none of which are techniques advisable for production purposes in 2017.
1
2 • Julian Fong, Magnus Wrenninge, Christopher Kulla, and Ralf Habel
AUTHORS
Julian Fong
Julian Fong is a senior software engineer at Pixar Animation Studios. He has worked on RenderMan
since 1999, with credits on all films since Finding Nemo. His key contributions to the renderer include
enhancements to the REYES algorithm, hierarchical and Loop subdivision surfaces, deep compositing,
optimization of ray tracing, and volume rendering.
Magnus Wrenninge
Magnus Wrenninge is the author of the book Production Volume Rendering and the Sci-Tech awarded
open source project Field3D. He started his career writing fluid simulation and environment rendering
software at Digital Domain, and in 2005 he joined Sony Imageworks where he worked both as a Senior
Software Developer and Lead Technical Director on films such as Alice in Wonderland and Oz: The
Great and Powerful. Since 2013 he is working as a Principal Engineer at Pixar Animation Studios, where
he focuses on all things related to rendering.
Christopher Kulla
Christopher Kulla is a principal software engineer at Sony Pictures Imageworks where he has worked
on the in-house branch of the Arnold renderer since 2007. He focuses on ray tracing kernels, sampling
techniques and volume rendering. In 2017 he was recognized with a Scientific and Engineering Award
from the Academy of Motion Picture Arts and Sciences for his work on the Arnold renderer.
Ralf Habel
Ralf Habel is a senior software engineer at the Walt Disney Animation Studios. He studied theoretical
physics at the University of Stuttgart and did a PhD in computer graphics at the Vienna University of
Technology. He was a Postdoctoral researcher at Disney Research Zurich before joining the Hyperion
team at Walt Disney Animation Studios focusing on volumes and level set rendering.
Production Volume Rendering • 3
Contents
Abstract 1
Contents 3
1 Introduction 5
2 Volume Rendering Theory 6
2.1 Properties of Volumes 6
2.1.1 Extinction and Single Scattering Albedo Parametrization 7
2.2 Light Propagation in Volumes 8
2.2.1 Radiative Transfer Equation 8
2.2.2 Volume Rendering Equation 9
2.3 Tracking Approach 10
2.3.1 Closed-form Tracking 10
2.3.2 Regular Tracking 12
2.3.3 Delta Tracking 13
2.3.4 Advanced Tracking Methods 15
2.4 PDF Approach 15
2.4.1 Transmittance Estimators 16
2.4.2 Path Directions and Reciprocity 17
2.4.3 Comparison of Approaches 18
2.4.4 Other Volume Rendering Methods 18
3 Adding volumes to a path tracer 19
3.1 Volume integrator execution model 20
3.2 Binding volumes to geometry 24
3.3 Light integrator 27
3.4 Transmittance rays 29
3.5 Heterogeneous volumes 31
3.6 Single scattering 33
3.6.1 Closed-form tracking approach 34
3.6.2 PDF approach 40
3.7 Multiple scattering 44
3.8 Emission 49
3.9 Overlapping volumes 51
4 Optimization 57
4.1 Multiple sampling 57
4.2 Importance sampling for Single Scattering 58
4.2.1 Uniform sampling and MIS 58
4.2.2 Equiangular Sampling 60
4.2.3 Equiangular Sampling from Area lights 62
4.2.4 Equiangular sampling in Heterogeneous media 62
4.2.5 Implementing equiangular sampling in a renderer 64
4.3 Importance sampling for Multiple Scattering 64
4.4 Tracking improvements 65
4.4.1 Residual and ratio tracking 65
4.4.2 Acceleration structures for tracking 67
5 Motion Blur 74
4 • Julian Fong, Magnus Wrenninge, Christopher Kulla, and Ralf Habel
1 INTRODUCTION
The last SIGGRAPH courses on production volume rendering were held in 2011 (Wrenninge and Bin Zafar
2011; Wrenninge et al. 2011). A year later, a book (Wrenninge 2012) by the same name was published,
summarizing and elaborating on much of the work. To say that the field has moved fast since then is
an understatement: in only six years, the entire field has shifted, and nearly all of the techniques and
methods presented at the time have since been superseded. Thanks to significant advances in techniques
and increases in computational power, path tracing has now become the predominant rendering method
used in movie production, entirely eliminating scanline algorithms. Where raymarching once served as
the go-to rendering method, tracking algorithms (inherited from nuclear and plasma physics) are now
the norm. Pre-computed lighting and multipass techniques are now also a thing of the past, along with
the methods that were used for modeling the voxel buffers and the motion blur techniques of the time.
A set of ad-hoc models for light propagation have made way for rigorous implementations of physically
accurate light transport, and in the process a number of “holy grail” goals have been achieved: unbiased
volume rendering, along with true area light sources, multiple scattering and accurate motion blur.
Effects that were unthinkable only a half decade ago are now available in off-the-shelf renderers.
Nonetheless, volume rendering still provides its own set of unique challenges that can be daunting
to path tracer developers and researchers. Volumes are computationally expensive to render, far more
so than any other type of geometry. Yet the choice of integration technique to solve this expensive
problem is not at all straightforward. Faster methods such as the use of tracking are unbiased and have
low overhead, but suffer from high variance. Slower methods may be biased or require high setup costs,
but have lower variance or may even be noise free. It may even be the case that no single approach is
best for a single ray traversing the scene! Meanwhile, the sheer amount of data associated with large
volumes means that traditional techniques for motion blur cannot be used. To add to the complications,
production scenes vary tremendously in scale and complexity: complicated explosions may be combined
with simple atmospherics in a single scene, and it is important to render each element as efficiently as
possible.
This course picks up where the last ones left off, explaining not only the basic theory underpinning
these recent advances, but also presenting a detailed and concrete look at their implementations. The
authors bring the experience of producing two commercially available (RenderMan and Arnold) and
one state-of-the-art proprietary renderer (Hyperion), and many of the key features of these are explored
and described. The course will focus on the fundamentals of adding volume rendering to an existing
path tracer, including all the practical aspects necessary for the demands of feature film work. The basic
theory of volume rendering will be presented, which will lead to a comprehensive overview of different
volume integration scenarios, along with the merits and weaknesses of techniques that are useful for
dealing with each scenario. Recent advances for the optimization of motion blur, variance reduction,
tracking, and dealing with scene complexity will also be presented.
6 • Julian Fong, Magnus Wrenninge, Christopher Kulla, and Ralf Habel
Table 1. Nomenclature
Symbol Description
x Position
t Ray parameter
ω Ray direction
xt Parameterized position along a ray: xt = x + tω
σa (x) Absorption coefficient
σs (x) Scattering coefficient
σt (x) Extinction coefficient: = σa (x) + σs (x)
α(x) Single scattering albedo: = σs (x)/σt (x)
fp (x, ω, ω 0) Phase function
d Ray length/domain of volume integration: 0 < t < d
ξ,ζ Random numbers
L(x, ω) Radiance at x in direction ω
Ld (xd , ω) Incident boundary radiance at end of ray
Le (x, ω) Emitted radiance
Ls (x, ω) In-scattered radiance at x from direction ω
Absorption. Absorption, expressed with the coefficient σa (x), describes the collision when a photon
is absorbed by the volume, simply disappearing from the domain we are interested in. Physically,
the photon energy is transferred into some volume particle internal energy such as translational or
vibrational modes in molecules, or more generally into heat.
Production Volume Rendering • 7
Scattering. A scattering collision σs (x) scatters the photon into a different direction defined by the
phase function. The radiance value carried by the photon does not change with a scattering collision;
any change in radiance is modeled with absorption and emission.
Phase Function. The phase function fp (x, ω, ω 0) is the angular distribution of radiance scattered and
is usually modeled as a 1D function of the angle θ between the two directions ω and ω 0. Phase functions
need to be normalized over the sphere:
∫
fp (x, ω, ω 0)dθ = 1 (1)
S2
otherwise phase functions would add or subtract radiance to a scattering collision. An important
property of phase functions — similar to BSDFs — is reciprocity. We need to be able to interchange
the directions without changing the value of the phase function. In a sense, the phase function has the
same functionality as the BSDF in surface rendering and can be abstracted as a BSDF as described in
section 3.6. Volumes that are isotropic have an equal probability of scattering incoming light in any
direction, and have an associated phase function:
1
fp (x, θ ) = (2)
4π
Anisotropic volumes can exhibit complicated phase functions which can be accurately modeled by
using the Mie solution to Maxwell’s equations (Mie scattering), or by using the Rayleigh approximation.
As an alternative to these expensive functions, in production volume rendering, the most widely used
phase function is the Henyey-Greenstein phase function (Henyey and Greenstein 1941):
1 1 − д2
fp (x, θ ) = (3)
4π (1 + д2 − 2д cos θ ) 32
where −1 < д < 1. The single parameter д can be understood as the average cosine of the scattering
directions, and controls the asymmetry of the phase function — it can model backwards scattering
(д < 0), isotropic scattering (д = 0), and forward scattering (д > 0). Multiple lobes of this phase function
can be combined to approximate more complicated phase functions. The Henyey-Greenstein phase
function has the property that it can be easily perfectly importance sampled (Pharr and Humphreys
2010).
Emission. Volumes emit radiance in a volumetric fashion, but otherwise behave exactly like any other
light source. The emitted radiance is expressed as a radiance field Le (x, ω) whose output gets absorbed
and scattered like any non-volume light source. If a volume does not emit, Le (x, ω) is simply zero. In
any real-world scenario, volumes do not emit directionally, and Le (x, ω) is the same in all directions w.
2.1.1 Extinction and Single Scattering Albedo Parametrization. In many cases, it is desirable to choose
a different parametrization than absorption and scattering coefficients. We can define the extinction
coefficient σt = σa + σs (sometimes called the attenuation coefficient, and often informally referred to
as the density) as the sum of the absorption and scattering coefficients. Extinction defines the net loss of
radiance due to both absorption and scattering, and we can model that loss with a single coefficient. We
can interpret an extinction collision as a collision where both scattering and absorption are involved
and we need to make sure that the scattered radiance is correctly modulated in the integral formulations
with the single scattering albedo.
The single scattering albedo α = σs /σt is defined in addition to the extinction to unambiguously
define volume properties. α has a similar meaning to the surface albedo: both are a measure of overall
reflectivity that determines the amount of scattered radiance. An α = 0 means that all radiance is
8 • Julian Fong, Magnus Wrenninge, Christopher Kulla, and Ralf Habel
absorbed (such as in black coal dust) and an α = 1 means that no absorption occurs and we have lossless
scattering (such as in clouds).
In more practical terms, extinction and single scattering albedo provide a good parametrization to
represent volumes since the albedo usually stays constant for a single type of volume while the extinction
is driven by a density field represented by voxels or a procedural function. The parametrization can be
changed at any time to the needs of computation or data storage.
where S 2 denotes the spherical domain around the position x. The σs in front of the integral models
the scattering of the incoming radiance from all of the directions similar to the σs in equation 5. The
radiance beam essentially picks up all of the radiance scattered into its own direction from all other
directions.
Production Volume Rendering • 9
Assembling the RTE. For the final form of the RTE, we add up all constituent terms. Due to their fun-
damental similarity, we combine absorption and out-scattering into the previously discussed extinction
coefficient σt (x) = σa (x) + σs (x):
∫
(ω · ∇)L(x, ω) = −σt (x)L(x, ω) + σa (x)Le (x, ω) + σs (x) fp (x, ω, ω 0)L(x, ω 0)dω 0 (8)
S2
2.2.2 Volume Rendering Equation. The RTE formulates the radiance distribution in a forward-
transport fashion using gradients (ω · ∇), defining what happens to a radiance beam as it travels
forward. The RTE can be directly used in finite element methods such as radiosity (Cohen et al. 1993)
and more generally in finite element methods, but not in a path tracing setting. The volume rendering
equation can provide this formulation. To simplify the notation, we shorten the in-scattering with
∫
Ls (x, ω) = fp (x, ω, ω 0)L(x, ω 0)dω 0. (9)
S2
We can formally integrate both sides of the RTE, turning the gradient (ω · ∇) on the left side of
Equation 8 into an integral on the right side, giving an explicit equation for L(x, ω) and arriving at the
volume rendering equation (VRE):
∫ d ∫ t h i
L(x, ω) = exp − σt (xs )ds σa (xt )Le (xt , ω) + σs (xt )Ls (xt , ω) + Ld (xd , ω) dt (10)
t =0 s=0
In order to express this formal solution, we parametrize the integrals along the negative part of the
radiance beam, with the running ray parameters t and s, and where the ray ends at a boundary (surface
or potentially other volume) modeled with the ray parameter d. The positions for the integrals over
ds and dt in Equation 10 are xt = x − tω and xs = x − sω. The incident radiance at the end of the ray
is modeled with Ld (xd , ω). Choosing this parametrization along the negative part of a radiance beam
follows naturally from the formal integration. Instead of describing where the radiance is traveling
to with a forward-transport formulation as done by the RTE with gradients, the VRE describes the
radiance in terms of where it comes from, looking backwards and accumulating all of the contributions
with integrals. With that, it is also ensured that the direction ω is always pointing in the direction of
radiance flow. Many descriptions such as PBRT (Pharr and Humphreys 2010) need to introduce switched
directions and need to keep track of the direction using arrows in the notation which adds unnecessary
complexity to the mathematical formulation.
For better structure, we shorten the exponential integral term with
∫ t
T (t) = exp − σt (xs )ds (11)
s=0
10 • Julian Fong, Magnus Wrenninge, Christopher Kulla, and Ralf Habel
which is the transmittance from the origin x of the ray to the position xt = x−tω on the ray parametrized
by t. The transmittance T (t) is the net reduction factor from absorption and out-scattering between x
and xt , combining these constituents. Additionally, we can execute the integral for the boundary term
since the term is not dependent on t, arriving at a more compact form of the VRE that fits our needs in
path tracing:
∫ d h i
L(x, ω) = T (t) σa (x)Le (xt , ω) + σs (x)Ls (xt , ω) dt + T (d)Ld (xd , ω) (12)
t =0
Any radiance picked up at a point on the ray needs to be extinguished by the transmittance up to
that point to calculate its final contribution to L(x, ω). Figure 3 shows a visualization of the VRE
corresponding to the contributions in Equation 12. The volume rendering equation can be interpreted as
a generalization of the rendering equation (Kajiya 1986) to include volumetric structures while surfaces
are nearly infinitely dense volumes with complex phase functions.
There are two principal stochastic approaches in Monte Carlo that can be used to solve the RTE. In
the following section, we derive the specialized versions of the volume rendering equations for each of
the approaches.
For the homogeneous volume where σt is not spatially varying, the transmittance becomes
T (t) = exp (−σt t) (13)
which is the Beer-Lambert law: exponential extinction of radiance. For tracking, we are interested in
creating a transmittance estimate that can double as a free-flight estimator; we want to sample and
generate a distance that a photon travels in a volume defined by a constant transmittance. The problem
breaks down to importance sampling an exponential function to produce a free-path distance t 0. The
PDF to do so is defined by normalizing the integral of the exponential function of the transmittance:
p(t) = σt exp (−σt t). (14)
We can perfectly importance sample the PDF with (Pharr and Humphreys 2010):
t 0 = − ln (1 − ξ )/σt (15)
There is no explicit Monte Carlo weight involved since the underlying exponential PDF is perfectly
importance sampled (producing a weight of 1) and we can interpret the t 0 directly as the distance a
photon travels. With the PDF in (14), we have a stochastic substitution for the transmittance (Equation
11) in the VRE (Equation 10). Substituting Equation 14 into the simplified VRE for homogeneous volumes
(i.e. with constant coefficients) is then
∫ d hσ
a σs i
L(x, ω) = p(t) Le (xt , ω) + Ls (xt , ω) dt. (16)
t =0 σt σt
We need to divide the other terms by σt to account for the normalization factor in Equation 14. We drop
the boundary term Ld (xd , ω) since it is cumbersome to express in math notation and will add it back at
the end of the section.
The second part of the VRE which contains the radiance contributions is estimated by a Russian
roulette that determines which type of collision is sampled: either absorption/emission or in-scattering.
The stochastic estimate of the transmittance already brought the other terms into the right form, and
we can interpret them as probabilities:
σa σs
Pa = , Ps (x) = (17)
σt σt
where Pa (x) + Ps (x) = 1 and like before σt = σa + σs . The probabilities are the ratios of each collision
type to the sum of all collision types. A Russian roulette chooses which type is modeled for each instance.
To arrive at a recursive formulation for Equation 16, recursing on a new estimate every time a scattering
event is chosen, we define x0 ≡ x and x j+1 = x j − t j ω j
∫ ∞ h i
L(xj , ω j ) = p(t j ) Pa Le (xj+1 , ω j ) + Ps Ls (xj+1 , ω j ) dt. (18)
t =0
To re-introduce boundaries into the approach, we need to split off the tail of the integral (d, ∞):
∫ d h i ∫ ∞
L(xj , ω j ) = p(t j ) Pa Le (xj+1 , ω j ) + Ps Ls (xj+1 , ω j ) dt + Ld (xd, j , ω j ) p(t j )dt (19)
t =0 t =d
The second integrand is not dependent on t, there is only a single contribution at the boundary xd, j .
This translates algorithmically into a simple test that if we hit a boundary before any of the collision
types are sampled (t > d), we return the boundary radiance Ld (xd , ω j ).
Translating Equation 19 into pseudo code formulating the closed-form tracking is given in Algorithm
1. Figure 4 shows some example paths generated by tracking.
12 • Julian Fong, Magnus Wrenninge, Christopher Kulla, and Ralf Habel
Fig. 4. A tracking path scattering once and absorbing, picking up some emission (top) and a path scattering before
hitting a boundary (bottom).
Algorithm 1: Closed-form tracking. We assume that the phase function fp (ω) is perfectly importance
sampled.
1 function ClosedFormTracking(x, ω, d)
2 while true do
ln(1−ζ )
3 t ← σt // Set new t for the current x
4 if t > d then // A boundary has been hit
5 return Ld (xd , ω)
6 x ← x−t ×ω
7 if ξ < σσat then // An absorption/emission collision has occured
8 return Le (x, ω)
9 else // A scattering collision has occured
10 ω ← sample ∝ fp (ω)
11 d ← new ray end in ω
Though simple, this method is highly relevant for production rendering — atmosphere and fog are
almost always modeled using homogeneous volumes. For homogeneous volumes bounded by geometry
and with a translucent surface shader, closed-form tracking can be used for path-traced subsurface
scattering to render skin or any other subsurface scattering.
2.3.2 Regular Tracking. In piecewise constant volumes, we can apply closed-form tracking to each
of the piecewise constant domains, simply traversing into the next domain if we do not scatter. We
can interpret the surface radiance Ld (xd , j, ω j ) as coming not from a hit surface, but rather a different
Production Volume Rendering • 13
Fig. 5. Regular tracking applies closed-form tracking in piecewise constant domains, restarting the tracking at
each boundary if the boundary is hit.
volume. In order to be efficient, this approach needs large parts of the volume to be homogeneous to be
efficient.
2.3.3 Delta Tracking. Delta tracking is based on von Neumann’s (1951) rejection sampling. It was
independently developed in neutron transport (Bertini 1963; Woodcock et al. 1965; Zerby et al. 1961)
and in plasma physics (Skullerud 1968), and is known also as Woodcock tracking, the null-collision
algorithm, or pseudo scattering.
The key to sampling free-path distances in heterogeneous volumes is to introduce a fictitious collision
type that homogenizes the total collision density in such a way that the sampling strategy as used
in closed form tracking sees a homogeneous (constant) volume. In this new type of collision, called
null-collision, the volume scatters in the same direction as the incoming direction, having no net effect
on the light transport itself. We express this collision type with the null-collision coefficient σn (x) which
acts in the same way as the physical coefficients. The physical collision coefficients are now spatially
variant, as is the null-collision coefficient σn (x). To homogenize the overall volume, we choose σn (x) in
such a way that the sum of all coefficients, the free-path coefficient σ̄ , becomes constant:
σ̄ = σa (x) + σs (x) + σn (x) = σt (x) + σn (x) (20)
A consequence of the need to be constant is that σ̄ is equal or greater to the maximum of σt (x) (sometimes
formulated as being a majorant of σt (x)):
σ̄ ≥ σt (x) (21)
and we can easily calculate σn (x) from
σn (x) = σ̄ − σt (x). (22)
Because σ̄ is constant, it can take on the role of the constant extinction σt in Equation 14 and we can
draw a distance sample in the very same way as in the closed-form tracking:
pn (t) = σ̄ exp (−σ̄t). (23)
We now have three collision types instead of two, resulting in the definition of a triple of probabilities:
σa (x) σs (x) σn (x)
Pa (x) = , Ps (x) = , Pn (x) = (24)
σ̄ σ̄ σ̄
that includes the null-collisions in the form of a collision probability with Pa (x) + Ps (x) + Pn (x) = 1.
14 • Julian Fong, Magnus Wrenninge, Christopher Kulla, and Ralf Habel
Fig. 6. A Delta-tracked path. If a null-collision event is chosen by the Russian roulette (x1 and x 3 ), the path is
continued unaltered.
Applying the additional null-collision probability to the VRE gives the recursive form similar to
Equation 18:
∫ ∞ h i
L(xj , ω j ) = pn (t j ) Pa (x)Le (xj+1 , ω j ) + Ps (x)Ls (xj+1 , ω j ) + Pn (x)L(xj+1 , ω j ) dt. (25)
t =0
The recursive evaluation as an algorithm of Equation 25 is very similar to the closed-form version of
tracking. The Russian roulette at the position t now chooses between three instead of two collision
types. If the null-collision type is chosen, the recursion simply goes into the next iteration without
altering the ray beam. Figure 6 shows a visualization of an example Delta-tracked path. Algorithm
2 shows the addition of the null-collision to the tracking process. Since we treat a null-collision like
any other collision, but continue in the same direction from the collision point x (set in line 6), we can
calculate the updated d from the previous d instead of tracing an intersection ray like in the scattering
collision.
Algorithm 2: Delta tracking. We assume that the phase function fp (ω) is perfectly importance sampled.
1 function DeltaTracking(x, ω, d)
2 while true do
ln(1−ζ )
3 t ← − σ̄ // Set new t for the current x
4 if t > d then // A boundary has been hit
5 return Ld (xd , ω)
6 x ← x−t ×ω
7 if ξ < σaσ̄(x) then // An absorption/emission collision has occured
8 return Le (x, ω)
9 else if ξ < 1 − σnσ̄(x) then // A scattering collision has occured
10 ω ← sample ∝ fp (ω)
11 d ← new ray end in ω
12 else // A null collision has occured
13 d ←d −t // Update d in relation to the collision x, ω does not change
Fig. 7. Emission sampling in the PDF approach. A PDF is built, a sample is drawn and the result is extincted up to
the sampled point.
The general solution is to subdivide volumes using an acceleration structure into domains where a tight
σ̄ can be delivered to the Delta tracking.
Delta Tracking in Extinction and Albedo Parametrization. Algorithm 2 can also be formulated by
aggregating the probabilities Pa (x) and Ps (x) into a single probability Pt = σσ̄t , followed by a Russian
roulette based on the single scattering albedo α. The drawback of this formulation is that emission is
not easily integrated since absorption and emission is not separately modeled from scattering.
2.3.4 Advanced Tracking Methods. The restriction on σ̄ needing to be a majorant can be remedied
by applying weighted tracking (Carter et al. 1972; Cramer 1978). Recently Kutz et al. (2017) introduced
trackers that can incorporate spectral data and minimizes lookups to the coefficients in addition to
removing the majorant restriction. We are not principally restricted to the probabilities shown in
equation 17; they can be manipulated to overcome the restrictions of Delta tracking. (Kutz et al. 2017)
also contains a formal generalization of the null-collision principles, the null-collision radiative transfer
equation which is compatible with the discussion in this section.
Fig. 8. In-scattering sampling in the PDF approach. A PDF is built, a sample is drawn and its in-scattering is
sampled recursively. The sample needs to be extinguished up to the sample point according to the transmittance.
is sampled by creating a new ray which recursively needs to deliver an approximation of its radiance
with a transmittance approximation and its own in-scattering approximation. Like in the emission case,
the result needs to be extinguished up to the sample point (see Figure 8). We can build completely
different PDFs for each term, optimizing for the underlying data in whichever way we deem necessary.
To correctly extinguish the contributions to L(x, ω), we need an estimator for the transmittance T (t)
for all of the terms in Equation 26 in addition to the estimators for the radiances. The transmittance
estimator needs to be evaluated for each sampling position, but as we will late see we can cache the
transmittance estimate to avoid reevaluating the transmittance.
The inherent challenge to this approach,as well as opportunity to optimize, is to efficiently build
the PDFs as accurately as possible to get efficient sampling. This PDF building is time consuming and
usually several samples are drawn from the same PDF to amortize the building costs.
2.4.1 Transmittance Estimators.
Ray Marching Transmittance Estimator. The transmittance can be estimated with quadrature instead
of Monte Carlo, essentially marching along the ray (Perlin and Hoffert 1989) and accumulating the
transmittance. This introduces bias even if the marching is jittered (Raab et al. 2008), resulting in artifacts
if the volume structure is undersampled. In the context of Monte Carlo, the ray marching transmittance
estimator is noise free, but very expensive to do on a per ray basis. But a practical advantage of ray
marching in the context of Monte Carlo integration is that no additional data is needed: ray marching
does not need the free-path coefficient σ̄ like the unbiased methods. In production, a ray marching
transmittance with very small step sizes can be used as a reference to validate more sophisticated
implementations.
Delta Tracking Transmittance Estimator. We can use Equation 23 as a transmittance estimator in the
PDF approach, testing if a collision occurred before or after t. This estimator produces a transmittance
estimate of T (t) = 1 or T (t) = 0 due to the Russian roulette and is therefore a binary estimator. The binary
estimate is too inaccurate to be used efficiently in the PDF approach as it either does not extinguish or
discards the whole estimate.
Ratio Tracking Transmittance Estimator. An unbiased transmittance estimator that is related to Delta
tracking is introduced to computer graphics by Novák et al. (2014). The Russian roulette of Delta tracking
is replaced by a Monte-Carlo weight T that is equal to the probability of a null collision in relation to
Production Volume Rendering • 17
Fig. 9. Ratio Tracking producing and estimate for the transmittance T(t) to a boundary xd .
Advanced Transmittance Estimators. In addition to Ratio tracking, Novak et al. (2014) introduced a
more sophisticated Ratio tracking method, called Residual Ratio tracking that uses a coarse control
transmittance to minimize the number of lookups to the volume parameters. It will be discussed in 4.4.1.
2.4.2 Path Directions and Reciprocity. While walking backwards on a ray or path representing
L(x, ω) is a consistent way to express the theory, adhering to the physical flow direction of radiance,
18 • Julian Fong, Magnus Wrenninge, Christopher Kulla, and Ralf Habel
class BSDF {
public:
BSDF(ShadingContext &ctx) : m_ctx(ctx) {}
virtual void EvaluateSample(RendererServices &rs, const Vector &sampleDirection, Color
&L, float &pdf) = 0;
virtual void GenerateSample(RendererServices &rs, Vector &sampleDirection, Color &L,
float &pdf) = 0;
protected:
ShadingContext &m_ctx;
};
class ShadingContext {
public:
20 • Julian Fong, Magnus Wrenninge, Christopher Kulla, and Ralf Habel
We assume the light integrator module is responsible for implementing a path tracing algorithm
with the aid of a RendererServices object, which provides services for tracing a ray against the scene
database, for sampling lights in the scene, and for creating a ShadingContext given a hit point on a
piece of geometry.
class RendererServices {
public:
float GenerateRandomNumber();
float MISWeight(int nsamps1, float pdf1, int nsamps2, float pdf2);
Point GetNearestHit(const Ray &ray, Geometry &g);
ShadingContext CreateShadingContext(const Point &p, const Ray &wi, Geometry &g);
void GenerateLightSample(const ShadingContext &ctx, Vector &sampleDirection, Color &L,
float &pdf, Color &beamTransmittance);
void EvaluateLightSample(const ShadingContext &ctx, const Vector &sampleDirection,
Color &L, float &pdf, Color &beamTransmittance);
void EvaluateLightSample(const ShadingContext &ctx, const Vector &sampleDirection,
Color &L, float &pdf);
};
public:
Volume(ShadingContext &ctx) : m_ctx(ctx) {}
virtual ~Volume() {}
virtual bool Integrate(RendererServices &rs, const Ray &wi, Color &L, Color
&transmittance, Color &weight, Point &P, Ray &wo, Geometry &g) = 0;
virtual Color Transmittance(RendererServices &rs, const Point &P0, const Point &P1) = 0;
protected:
ShadingContext &m_ctx;
};
We will also tie this interface to the compact form of the VRE as shown in equation 12 (repeated
here):
∫ d h i
L(x, ω) = T (t) σa (x)Le (xt , ω) + σs (x)Ls (xt , ω) dt + T (d)Ld (xd , ω)
t =0
A Volume is constructed using a ShadingContext, which is initially the geometric environment of
the hit point which begins the volume interval. The point returned by ShadingContext::GetP() is
the position x0 . As we will describe later, this hit point may not actually be from a piece of geometry to
which the volume’s originating Material has been bound.
Volume integration is initiated by the Integrate method. The input to the Integrate method is
the ray with direction ω and origin x0 , denoting the direction of the volume interval (chosen by the
BSDF::GenerateSample executed at the hit point x0 ), and a RendererServices object that the Volume
can use during integration. The outputs include the radiance along the ray L and the weight of this
radiance estimate; these two outputs are the estimate of the integrand term in the VRE.
The outputs also include the beam transmittance over the volume integration interval, and the
hit point P, incident ray wo into the hit point, and geometry corresponding to the end of the volume
integration interval. In other words, the volume integrator actually picks the distance d and returns xd
in the output parameter P, and also returns T (d) in the output parameter transmittance. The reason
for this flexibility is to allow the light integrator to call the Volume::Integrate method to generate the
next hit, instead of calling RendererServices::GetNearestHit with the outgoing ray from a BSDF;
we will see in section 3.7 how these outputs can facilitate multiple scattering in the volume.
We will discuss how the Volume::Transmittance method is used in section 3.4, but for now consider
it a method which returns the beam transmittance between two points inside the volume.
A complete but trivial volume implementation looks like this:
weight = Color(1.0);
wo = Ray(P, wi.dir);
return true;
}
virtual Color Transmittance(RendererServices &rs, const Point &P0, const Point &P1) {
return Color(1.0);
}
};
In EmptyVolume, the Integrate method does nothing more than call the RendererServices’s
GetNearestHit method to generate the next hit point and geometry. This renderer service will trace a
ray against the geometry in the scene, and here we assume that when we trace the ray it will return a
hit at the next interesting geometry interface; we will discuss this more in the next section. The incident
ray into that hit point gets the same direction as the input ray wi passed to the Integrate method. An
empty volume emits no radiance (Le = Ls = 0) and has no effect on the transmittance (T (d) = 1), so the
transmittance field is set to 1.0 in both the Integrate and Transmission methods.
A slightly less trivial volume which implements homogeneous absorption as described by the Beer-
Lambert law looks like this:
the interval and the hit point, and assign e −σt d (equation 13) to the transmittance T (d). Other than being
used to measure the distance to the end of the volume, the hit point xd is of no further use to the volume
integration itself; it may in fact belong to an entirely different and unrelated piece of geometry. The
volume integrator simply returns this hit point (and its associated geometry) back to the light integrator,
which is ultimately responsible for treating this information as the next vertex on the integration path
and computing Ld .
Bear in mind that in this system, a volume integrator does not exist by itself; it is a component of a
Material controlling only the volumetric integration inside a piece of geometry. The surface properties
of that geometry are represented by the BSDF returned by the CreateBSDF method of that Material. In
order to finish defining a Material, we need to define a TrivialBSDF, whose GenerateSample method
used for creating indirect rays simply continues a ray in the outgoing direction with full weight and PDF.
The resulting material combining both the TrivialBSDF and the BeersLawVolume now fully defines a
volumetric region with no surface properties which absorbs light.
Listing 4. A trivial BSDF representing an interface boundary with no effect, and a Material incorporating same
class TrivialBSDF : public BSDF {
public:
TrivialBSDF(ShadingContext &ctx) : BSDF(ctx) {}
virtual void EvaluateSample(RendererServices &rs, const Vector &sampleDirection, Color
&L, float &pdf)
{
pdf = 0.0;
L = Color(0.0);
}
virtual void GenerateSample(RendererServices &rs, Vector &sampleDirection, Color &L,
float &pdf) {
sampleDirection = -m_ctx.GetV();
pdf = 1.0;
L = Color(1.0);
}
};
};
Of course, the same BeersLawVolume may be combined with a more complicated BSDF to create
materials with both interesting surface and volumetric behavior. Figure 10 shows a glass material
without and without BeersLawVolume. (Note that the teapot in the figure is a properly modeled teapot
with thin walls.)
Fig. 10. Left: BeersLawMaterial, a material which combines BeersLawVolume with TrivialBSDF. Center: a
material with a glass BSDF only and no volume. Right: a material combining a glass BSDF with BeersLawVolume.
p2
ωr
n0 p0
ωt
ωi ωr ωt
ωi n1
p1 p1
Fig. 11. Left: A ray intersecting the outside of a volume. In the case of a transmit event, a volume integration
domain is created starting at point p0 ; the volume integrator is responsible for calculating the end of its integration
domain, potentially at point p1 . Right: A ray intersecting the inside of the same volume. In the case of a reflect
event, another volume integration domain is created starting at point p1 ; the volume integrator is responsible for
ending its integration domain, potentially at point p2 .
In the case of a transmit event, the BSDF::GenerateSamples evaluates a BTDF and creates an
outgoing ray with direction ωt . In the case of a surface-only render, the light integrator would normally
simply trace this ray against the scene database, create another shading event, and proceed as before.
However, because our material is volume capable, we instead ask the material to create an instance of a
Volume. The outgoing ray with direction ωt is now an input to this Volume object, which is responsible
for computing several outputs related to volume integration, as well as potentially tracing the ray against
the scene database (by using the GetNearestHit method of the RendererServices object which is
made available to the Volume) in order to find the end of the volume integration domain (in this case,
the point p1 ).
After the volume integration has executed, we are interested in what happens when the light integrator
continues the integration and deals with a ray which hits the inside of the same object, as shown on
the right in figure 11. Here, the incoming ray direction ωi and the surface normal n1 point in the same
direction: their dot product is positive. In this situation, again one of two situations may now occur: the
BSDF::GenerateSamples method will either choose a reflection event or a transmit event. In the case
of reflection, the resulting ray with direction ωr has not left the interior of the object, and therefore
has not left the volumetric region. Thus, another instance of the volume object must be created with
input ωr . In the case that the material instead selects a transmit event, the BSDF will create a ray with
direction ωt which has now left the volume object, and no volume needs to be created.
So far, we have considered only a single volume object, with a single material binding. Things are
more complicated when multiple objects are involved. To help disambiguate situations such as this, we
can utilize the concept of opposite and incident volumes: the opposite volume to an incident ray is the
volume on the opposite side of the surface, while the incident volume to an incident ray is the volume
on the same side of the surface. On the left of figure 11, the incident ray had an opposite volume but no
incident volume, while on the right in the same figure the incident ray had an incident volume and no
opposite volume. Now consider the situation of a volume object enclosing a smaller non-volumetric
object, as shown in figure 12.
26 • Julian Fong, Magnus Wrenninge, Christopher Kulla, and Ralf Habel
p2
n1
p1
p0
Fig. 12. A ray intersecting a non-volumetric object inside a volume. The volume binding between p1 and p2 has
nothing to do with the Material of the non-volumetric object; it came from the Material bound to the Geometry
at p0
At p1 , there is no opposite volume because the enclosed red sphere is non- volumetric. However,
there is definitely an incident volume. It is the same incident blue volume that was bound to the outer
enclosing object. It is clear from this situation that the Volume object that needs to be executed at a hit
point may actually have no relation with the Material binding of the intersected object; it may have
been created from a previous Material encountered along the ray path.
This leads to an implementation where rays that are moving through our system must be aware of
the Material that they are moving inside. Essentially, our rays must know what volume(s) they are
inside. When a ray intersects an object, they may enter a new volume, or they may leave a volume. This
can only occur on a transmit event; on a reflection event, they can neither enter a volume or leave a
volume.
Now consider the case of two nested volumes: an outer volume VO enclosing an inner volume VI , as
shown in figure 13.
VO
p2 VI
p1 p5
p0
p3
p4
Fig. 13. A ray intersecting a volume VI enclosed within another volume VO . The intervals [p1 , p2 ] and [p3 , p4 ]
require integration of both volumes.
At p1 , the incident volume is VO . If a reflection event occurs at p1 , then the incident volume is V0 ; this
will be the volume that integrates over the interval [p1 , p2 ]. If a transmit event occurs at p1 , then there
are two opposite volumes: VO and VI . Both volumes must be integrated over the interval [p1 , p3 ].
Production Volume Rendering • 27
At p3 , the incident volumes remain VO and VI . If a reflection event occurs at p3 , the incident volumes
remain unchanged, and both volumes integrate over the interval [p3 , p4 ]. If a transmit event instead
occurs at p3 , then we must note that we have exited the volume VI , leaving a single opposite volume
VO ; this is the volume that integrates over the interval [p3 , p5 ].
In order to accommodate the need for tracking a list of Materials per ray, we can add EnterMaterial
and ExitMaterial methods to the Ray data structure which add and remove a material from this list.
We will see in the next section how these methods are used by the light integrator to track which
volume should be used at an interface boundary.
int j = 0;
while (j < maxPathLength)
{
ShadingContext *ctx = rs.CreateShadingContext(P, ray, g);
Material *m = g.GetMaterial();
BSDF *bsdf = m->CreateBSDF(*ctx);
Ray nextRay(ray);
nextRay.org = P;
nextRay.dir = sampleDirection;
if (!rs.GetNearestHit(nextRay, P, g))
break;
ray = nextRay;
j++;
}
To incorporate volume rendering into this light integrator loop, we add some code after we have
picked the direction of the indirect ray with BSDF::GenerateSample. As previously mentioned, we
need to be aware of whether the indirect ray fired by the BSDF at the interface boundary is a transmit
event (fired into the surface) or a reflect event (away), as this controls whether we need to consider a
change in participating media. This is decided by comparing the sign of the dot product of the incoming
ray against the surface normal, against the sign of the dot product of the outgoing ray against the
surface normal. If a transmit event has indeed occurred, then a further decision is required: we need to
decide whether we have entered or exited an object, which is signaled by the sign of the dot product
of the ray direction against the normal. With the addition of the EnterMaterial and ExitMaterial
methods to rays in order to track volumes, we can insert the following code into the light integrator in
place of a simple call to RendererServices::GetNearestHit.
In this code, note that a single volume integrator will run over the interval, even if multiple volumes
overlap. We will explain why in section 3.9. After determination of this Volume, its Integrate method
is called instead of the call to RendererServices::GetNearestHit to allow the volume the chance
to compute the end of the volume integration interval xd , and any radiance contribution from the
volume Lv is added to the radiance estimate for the ray, weighted by the throughput so far. The beam
transmittance from the volume T (d) is itself multiplied into the throughput, and the inner loop of the
path tracer then returns to its normal execution.
involved the determination of shadow-casting occluders, but we will need to extend this mechanism to
handle intervening volumes and their attenuating affect on the beam transmittance.
These transmittance rays are usually treated as a special case by a renderer because they can easily
outnumber camera and indirect rays, and therefore deserve special optimization. One typical opti-
mization performed for transmittance rays is to allow them to intersect geometry in any order, rather
than in strict sorted depth-first order. This out-of-order execution is usually combined with early-out
optimizations: any opaque object hit by a transmittance ray will immediately cause the ray to terminate.
Furthermore, the importance of the efficient direct lighting may mean that in production rendering,
transmittance rays may be allowed to break some laws of physics. For example, a glass material that
normally must account for refraction on camera and indirect rays may choose to ignore such effects for
transmittance rays; this optimization allows for much faster convergence when direct lighting objects
behind glass, and may be visually acceptable if the glass is a thin material.
2 1 4 3 1 2 3 4 5 6
Fig. 14. Left: transmittance rays intersecting geometry can intersect the geometry in any order without affecting
the transmittance result. Right: transmittance rays intersecting volumes need to find the correct volume extents,
which requires intersection in depth first order. Moreover, correct tracking of volume entry and exit requires
computation of the normal at every hit point.
Given this special treatment, integrating volumes into the framework of transmittance rays poses a
few special problems. In a surface-only situation, either there is no need to shade a hit point (it is trivially
opaque), or an opacity shader needs to be executed on that single hit point. With volumes, we need
to intermingle the execution of Volume::Transmittance over a pair of hit points. This immediately
curtails the ability to perform out of order hit testing, as we must ensure that the two hit points truly
reflect the proper volume extents. Moreover, we must now track the proper volume bindings attached to
the transmittance ray as it makes it way through the scene. This is simplified somewhat in this situation
as by definition the transmittance ray must go through a surface and never reflects, so we never need to
perform the dot product between the outgoing ray direction and the incoming ray direction. However,
we still need to track whether the ray enters or leaves a volumetric material, which requires a dot
product between the ray direction and the surface normal at every hit point.
Finally, it is important to realize that direct lighting of a volume requires self-shadowing, which means
the transmittance ray from that volume must correctly track that it needs to compute the transmittance
through the same volume. In order to accurately capture this state of affairs, we require that transmittance
rays inherit the volume tracking state from the camera or indirect ray that intersected the hit point, and
also require the convention that transmittance rays are fired from the point of illumination towards the
light source.
Production Volume Rendering • 31
virtual bool Integrate(RendererServices &rs, const Ray &wi, Color &L, Color
&transmittance, float &weight, Point &P, Ray &wo, Geometry &g) {
if (!rs.GetNearestHit(Ray(m_ctx.GetP(), wi.dir), P, g))
return false;
L = Color(0.0);
transmittance = Transmittance(rs, P, m_ctx.GetP());
weight = Color(1.0);
wo = Ray(P, wi.dir);
return true;
}
virtual Color Transmittance(RendererServices &rs, const Point &P0, const Point &P1) {
float distance = Vector(P0 - P1).Length();
Vector dir = Vector(P1 - P0) / distance;
bool terminated = false;
float t = 0;
do {
float zeta = rs.GenerateRandomNumber();
t = t - log(1 - zeta) / m_maxAbsorption;
if (t > distance) {
break; // Did not terminate in the volume
}
if (terminated)
return Color(0.0);
else
return Color(1.0);
}
protected:
const float m_maxAbsorption;
const int m_absorptionProperty;
};
Production Volume Rendering • 33
Fig. 15. Single scattering. The volume integrator is responsible for computing the hit point all the way through the
volume, as well as an estimate of the in-scattered radiance (red dashed line) at a sample location (red square).
It is worth revisiting the simplified equation for the in-scattered radiance, equation 9, to determine
how to compute the direct lighting contribution at a point x in the volume:
∫
L(x, ω) = σs (x) fp (x, ω, ω 0)L(x, ω)dω 0
S2
By analogy to how multiple importance sampling (Veach 1997) works when computing direct lighting
for surfaces: we can estimate the value of this integral either by sampling the phase function; or by
sampling the light source; or we can do both and use multiple importance sampling to combine the
results. A path tracer which implements a BSDF interface along with direct lighting for surfaces already
has most of the pieces necessary to handle this integral estimation, and in fact can simply recast a
phase function in terms of a BSDF. Let’s assume that in such a path tracer, the RendererServices
object provides a GenerateLightSample method to sample the light database given a shading context
generated from a point; the method returns a sampled direction sampleDirection, the radiance L
arriving at the point from the sample direction, along with the associated probability density pdf and
the beamTransmittance between the light and the point. Similarly, a EvaluateLightSample method
can be used for BSDF sampling: given a shading context generated from a point and a sample direction
generated by a BSDF, the method returns the radiance L arriving at the point from the sample direction,
along with the associated probability density pdf and the beamTransmittance between the light and
the point. For both of these methods, the computation of beamTransmittance must involve the firing
of a transmission ray, and the discussion from section 3.4 is therefore relevant: we assume that the
implementation of transmission rays has already been altered as per the previous section to include
34 • Julian Fong, Magnus Wrenninge, Christopher Kulla, and Ralf Habel
the necessary calls to Volume::Transmittance as required for any intervening volumes (including the
current volume we are dealing with itself).
Assuming the renderer provides all these pieces already, we can begin with the simplest phase
function, isotropic scattering, and turn equation 2 into a BSDF:
Depending on the style of BSDF used for surfaces, you may be more used to a BSDF which multiplies
surface properties into the L term - for example, some form of diffuse color. It is quite easy to make
our phase functions look similar by using the parametrization described in section 2.1.1, in particular
the single scattering albedo α = σs /σt . As previously discussed, α is very similar to the surface albedo
and could naturally appear in our phase function masquerading as a BSDF. For the sake of clarity, in
the subsequent code we have chosen to keep the α term inside the single scattering volume integrator
itself, where it appears when we need σs (because σs = ασt ).
3.6.1 Closed-form tracking approach. In the closed-form tracking approach (section 2.3.1) applied to
single scattering, we estimate the radiance at a location x0 = x0 + t 0ω, using a Monte Carlo approach
to choose this location. As described in section 2.3.1, one initial approach would be to use a PDF
Production Volume Rendering • 35
based on normalizing the transmittance (equation 14), which in the homogeneous case we can perfectly
importance sample by using equation 15: t 0 = − ln (1 − ξ )/σt . If we implement things this way, we would
end up with a volume integrator that when combined with the lighting integrator would essentially be
the implementation of closed-form tracking as described in Algorithm 1.
We will instead depart from this approach slightly by noting that the PDF of equation 14 actually has
the domain 0 ≤ t < ∞, which is why the distance t 0 chosen by equation 15 may be greater than d (thus
necessitating the check t > d on line 4 of Algorithm 1). In practical terms, this means that using this
PDF may result in a sample location chosen outside the volume, and consequently no lighting estimate
of the volume will occur. This can lead to high variance for low density volumes lit by a strong light
source. We can instead create a new PDF which normalizes the integral of the exponential function of
transmittance over the domain 0 ≤ t < d, resulting in
σt exp (−σt t)
p(t) = (28)
1 − exp(−σt d)
which leads to a slightly modified importance sample function:
Listing 10. Single scattering homogeneous integrator using closed form tracking
class SingleScatterHomogeneousVolume: public Volume {
public:
SingleScatterHomogeneousVolume(Color &scatteringAlbedo, Color &extinction,
ShadingContext &ctx) :
Volume(ctx), m_scatteringAlbedo(scatteringAlbedo), m_extinction(extinction) {}
virtual bool Integrate(RendererServices &rs, const Ray &wi, Color &L, Color
&transmittance, Color &weight, Point &P, Ray &wo, Geometry &g) {
if (!rs.GetNearestHit(Ray(m_ctx.GetP(), wi.dir), P, g))
return false;
m_ctx.RecomputeInputs();
// Compute direct lighting with light sampling and phase function sampling
IsotropicPhaseBSDF phaseBSDF(m_ctx);
L = Color(0.0);
Color lightL, bsdfL, beamTransmittance;
float lightPdf, bsdfPdf;
Vector sampleDirection;
rs.GenerateLightSample(m_ctx, sampleDirection, lightL, lightPdf, beamTransmittance);
phaseBSDF.EvaluateSample(rs, sampleDirection, bsdfL, bsdfPdf);
L += lightL * bsdfL * beamTransmittance * rs.MISWeight(1, lightPdf, 1, bsdfPdf) /
lightPdf;
There are two items of note. First, the implementation of direct lighting within this volume should
be very close to the implementation of direct lighting for a surface, save for one important difference:
multiplication of the radiance by the geometric term ω · n required for surfaces is replaced by multipli-
cation by the scattering coefficient σs (which is itself the product of the extinction coefficient and the
scattering albedo). Second, two separate transmittance terms are computed by this integrator: one is the
transmittance over the entire volume interval T (d) (which is returned in the transmittance output
parameter), and the other is the transmittance T (t 0) (the local variable Tr), computed only up to the
location where scattering takes place. This second value is multiplied into the radiance returned (as
required by the integrand of the VRE, equation 12), but is not otherwise needed by the light integrator.
Production Volume Rendering • 37
Now, we can tackle the case of heterogeneous single scattering by combining BeersLawHeteroge-
neousVolume with SingleScatterHomogeneousVolume. Delta tracking can be used to determine the
scatter location: the distribution of the delta tracking termination locations has a PDF proportional
to the transmittance. Unlike the homogeneous case, there is no easy way to modify this PDF to be
normalized over a finite domain, so an implementation based on delta tracking cannot guarantee that a
sample will be taken inside the volume. The implementation of Transmittance is identical to that of
BeersLawHeterogeneousVolume and is not shown here.
m_ctx.SetP(Pl);
m_ctx.RecomputeInputs();
if (terminated)
{
// The shading context has already been advanced to the
// scatter location. Compute direct lighting after
// evaluating the local scattering albedo and extinction
Color scatteringAlbedo = m_ctx.GetColorProperty(m_scatteringAlbedoProperty);
Color extinction = m_ctx.GetColorProperty(m_extinctionProperty);
IsotropicPhaseBSDF phaseBSDF(m_ctx);
L = Color(0.0);
Color lightL, bsdfL, beamTransmittance;
float lightPdf, bsdfPdf;
Vector sampleDirection;
rs.GenerateLightSample(m_ctx, sampleDirection, lightL, lightPdf,
beamTransmittance);
phaseBSDF.EvaluateSample(rs, sampleDirection, bsdfL, bsdfPdf);
L += lightL * bsdfL * beamTransmittance * scatteringAlbedo * extinction *
rs.MISWeight(1, lightPdf, 1, bsdfPdf) / lightPdf;
wo = Ray(P, wi.dir);
return true;
}
Production Volume Rendering • 39
protected:
const int m_scatteringAlbedoProperty;
const float m_maxExtinction;
const int m_extinctionProperty;
};
There is one subtle difference between this and the homogeneous case: when using delta tracking,
the transmittance up to the scatter location is simply 1, so it does not need to be multiplied into the
lighting term. (The scattering coefficient σs does still need to be multiplied into the radiance, even if it is
subsequently cancelled out by multiplication with the inverse of the pdf which also contains this term.)
We can extend our scattering volume integrators to support anisotropy by implementing the Henyey-
Greenstein phase function (equation 3) as a BSDF. A single lobed variant parametrized by the anisotropy
term g is shown below, with results shown in figure 17.
Fig. 17. Varying the anisotropic term g with AnisotropicPhaseBSDF and single scattering. Left: g = -0.5 (backwards
scattering); center: g = 0.0 (isotropic scattering); right: g = 0.5 (forwards scattering). The red light is aimed towards
the camera, while the blue light is aimed away from the camera.
3.6.2 PDF approach. As described in section 2.4, the PDF approach to single scattering amounts to
∫d
building a PDF for sampling the integral t =0 T (t)σs (xt )Ls (xt , ω)dt from the separated VRE shown in
equation 26.
In order to reduce variance in the estimate, it is desirable to have the PDF be proportional to the
terms of the integrand which have the most variance. In the absence of this knowledge, especially
in the heterogeneous volume case, a standard way of constructing the PDF is to try to approximate
the entire integrand p(t) ≈ T (t)σs (xt )Ls (xt , ω), and take samples of p(t) at fixed intervals to create a
Production Volume Rendering • 41
discrete distribution. (If we let p(t) actually be the integrand instead of an approximation, then we may
as well compute the integral by quadrature rather than building and sampling a PDF.) We can then
apply inverse transform sampling to the distribution. The table of PDF values is converted to a discrete
cumulative density function (CDF) c(t) by normalization. We can now importance sample the PDF by
generating a random number ξ in the interval [0, 1) and finding the value of t with c(t) nearest to ξ by
searching the distribution of CDF values.
While straightforward, using inverse transform sampling on discrete samples has the same drawbacks
as using ray marching to estimate transmittance: it introduces bias, even if we jitter the interval size,
and for a single sample is extremely expensive compared to the tracking approach. However, using a
PDF p(t) which approximates all the terms of the integrand also means for a single sample we have the
potential to perform much better importance sampling; the PDF used in the tracking methods shown so
far are only proportional to the T (t) term, which means that if the variance in the integral is actually
due to the lighting term Ls , the importance sampling will not capture the source of variance, and the
tracking estimate will be much noisier.
The highest expense associated with this method is the computation of p(t) at regular intervals, and
most of that cost lies with approximating the L(x, ω) component of the Ls term: the in-scattered radiance
coming from lights (keeping in mind that here we are dealing strictly with single scattering, so L(x, ω)
is strictly from a light). Implementors of the PDF approach must weigh whether the computational
cost of better approximations to L(x, ω) are worth the decrease in variance. One trade off to consider
is that much of the cost of lighting is in the cost of firing a transmission ray, and calculating the
beam transmittance along that ray. Removing the beam transmittance from L(x, ω) will speed up the
calculation at the cost of making the estimate worse: areas of the volume that are shadowed (or self-
shadowed) will be overly sampled.
The following listing gives a simple example of using the PDF approach for single scattering. Sin-
gleScatterPDFVolume takes as argument a stepsize and builds a PDF using T (t), σs (xt ), and an ap-
proximation to Ls (xt , ω) using only a sample direction generated by the phase function and the lighting
response from the light without the beam transmittance. This response is handled by the four argument
variant of RendererServices::EvaluateLightSample, which will return results similar to the five
argument variant that we have been using, except that it will not compute the beam transmittance and
will not shoot a transmission ray. Note that in this listing, we do not specialize for the homogeneous
volume case, but doing so would be trivial (by eliminating the re-evaluation of the local extinction
coefficient and scattering albedo at each step). We also show in this listing how to evaluate transmittance
by quadrature, since its computation closely mirrors much of the steps of the PDF approach to single
scattering.
t += adjustedStepsize;
}
// Sample CDF
float xi = rs.GenerateRandomNumber();
for (int i = 0; i < nsteps; ++i) {
if (pdf[i] > xi) {
if (i == 0)
t = (xi / pdf[i]) * adjustedStepsize;
else
t = (i + (pdf[i] - xi) / (pdf[i] - pdf[i - 1])) * adjustedStepsize;
break;
}
}
delete[] pdf;
// Direct lighting
Color scatteringAlbedo = m_ctx.GetColorProperty(m_scatteringAlbedoProperty);
Color extinction = m_ctx.GetColorProperty(m_extinctionProperty);
IsotropicPhaseBSDF phaseBSDF(m_ctx);
L = Color(0.0);
Color lightL, bsdfL, beamTransmittance;
float lightPdf, bsdfPdf;
Vector sampleDirection;
rs.GenerateLightSample(m_ctx, sampleDirection, lightL, lightPdf, beamTransmittance);
phaseBSDF.EvaluateSample(rs, sampleDirection, bsdfL, bsdfPdf);
L += lightL * bsdfL * beamTransmittance * scatteringAlbedo * extinction *
rs.MISWeight(1, lightPdf, 1, bsdfPdf) / lightPdf;
transmittance = accumTrans;
weight = Color(1.0);
wo = Ray(P, wi.dir);
return true;
}
virtual Color Transmittance(RendererServices &rs, const Point &P0, const Point &P1) {
float distance = Vector(P0 - P1).Length();
int nsteps = (int) ceilf(distance / m_stepsize);
float adjustedStepsize = distance / nsteps;
44 • Julian Fong, Magnus Wrenninge, Christopher Kulla, and Ralf Habel
Color accumTrans(1.0f);
float t = 0;
for (int i = 0; i < nsteps; ++i)
{
// Update the shading context
Point Pl = P0 + t * Vector(P1 - P0);
m_ctx.SetP(Pl);
m_ctx.RecomputeInputs();
// Recompute the local extinction after updating the shading context
Color extinction = m_ctx.GetColorProperty(m_extinctionProperty);
// Compute transmittance over the step, accumulate
accumTrans *= Color(exp(extinction.r * -adjustedStepsize), exp(extinction.g *
-adjustedStepsize), exp(extinction.b * -adjustedStepsize));
t += adjustedStepsize;
}
return accumTrans;
}
protected:
const float m_stepsize;
const int m_scatteringAlbedoProperty;
const int m_extinctionProperty;
};
in-scatter along the infinite length of the ray comes from a single location: the nearest surface that is
hit. Therefore, the probability associated with that single location is 1, every other location along the
ray has a probability of zero, and the weight associated with the location is trivially 1 and therefore
unnecessary, as the in-scattering at the surface is the only single sample required for the in- scattering
over the entire ray.
In the case where there are volumes along a ray, this is no longer the case: there is potential for
in-scattering along the infinite ray extent wherever there is a volume, as well as the first opaque surface
behind all volumes. Since a forward path tracer still must stop at a single location along the ray, we
must now consider that wherever we stop can only be an estimate of the in-scatter along the infinite
extent of the ray. Therefore, we must associate a weight of the estimate along with our location choice.
To complicate matters even further: in our decoupled shading model, a volume has only enough
knowledge to compute a PDF p(t) along a finite extent 0 < t < d where d is the end of the volume
geometry. For the parts of the ray beyond the volume, the best that it can do is to compute a single
probability p(t ≥ d) for the sample location being anywhere t ≥ d, i.e. at the volume interface or beyond
it.
Fig. 18. Multiple scattering. Each invocation of the volume integrator (red lines) is responsible only for computing
the next hit point, the transmittance over the interval, and the weight associated with the location; all radiance
calculations are handled by the lighting integrator (black dashed lines).
To implement a tracking approach to multiple scattering, unlike the single scattering homogeneous
integrator, we want to use the PDF with unbounded domain proportional to the transmittance (equa-
tion 14) to decide the sample location: t 0 = − ln (1 − ξ )/σt . The probability associated with sampling
anywhere beyond the end of the volume p(t ≥ d) is computed by using the associated CDF c(t) of the
PDF: p(t ≥ d) = 1 − c(d), which happens to end up being exp(−σt d). With these PDFs, the implementa-
tion of a multiple scattering homogeneous volume is straightforward (the Transmittance method is
the same as SingleScatterHomogeneousVolume, and is not shown):
The key difference between this integrator and the single scattering integrator (besides returning a
radiance of zero) is that the P and Geometry g values returned are no longer always the value returned
by GetNearestHit. Instead, they may correspond to a scatter location within the volume. When this
Production Volume Rendering • 47
happens, we assume that ShadingContext::GetGeometry will return the same geometry which started
the volume renderer and return that to the lighting integrator, so that the next ray will invoke the same
volume integrator.
Note the weight returned by this integrator not only includes the inverse of the PDF, but also includes
σs when scattering inside the volume. The reason for this is that we assume the lighting integrator as
described in section 3.3 does not include this term required by equation 10 in its implementation of
direct lighting for surfaces, so it is convenient to include it directly in the weight output. (We should also
point out that the implementation of direct lighting for surfaces may also include the geometric term
ω · n, which is not required for volumes; if so, this needs to be accounted for in the lighting integrator
implementation, as the normal in a volume is typically defined to be zero length.)
An inspection of the weight, pdf, and transmittance terms will reveal that they all cancel each
other out when multiplied together in the lighting integrator. This is an expected result of using a PDF
normalized to the transmittance. While it may be tempting to eliminate all of these terms, any use of an
alternate PDF or multiple importance sampling will results in terms that no longer cancel out.
Note that the implementation of single scattering in the previous section involves a volume integrator
that guarantees a direct lighting sample will take place somewhere along the volume on the way to the
next interface. In other words, in the single scattering case, our path tracer which takes n steps will now
invoke direct lighting 2n − 1 times: n invocations at the surfaces, and n − 1 invocations at the volumes
in front of every hard surface. This is not the case for our implementation of multiple scattering: for
n steps, the lighting integrator will invoke direct lighting n times. This “branching factor” of 2 in the
single scattering integrator leads to a more converged (but more expensive) estimate of radiance for a
path for the same number of bounces due to the increased number of lighting calculations involved.
As we will describe later, due to the strong importance of contributions closer to the eye, it may be
worthwhile to blend between these two regimes depending on how far along we are on the path.
We can conclude our survey of integration techniques by examining the situation of multiple scattering
in heterogeneous volumes, which combines MultiScatterHomogeneousVolume with SingleScatter-
HeterogeneousVolume:
if (terminated) {
P = m_ctx.GetP() + t * wi.dir;
g = m_ctx.GetGeometry();
Color transmittance = Color(1.0f);
Color extinction = m_ctx.GetColorProperty(m_extinctionProperty);
Color pdf = extinction * transmittance;
Color scatteringAlbedo = m_ctx.GetColorProperty(m_scatteringAlbedoProperty);
// Note that pdf already has extinction in it, so we should avoid the
// multiply and divide; it is shown here for clarity
weight = scatteringAlbedo * extinction / pdf;
} else {
Color transmittance = Color(1.0f);
Color pdf = transmittance;
weight = 1.0 / pdf;
}
L = Color(0.0); // No estimate of radiance
wo = Ray(P, wi.dir);
return true;
}
protected:
const int m_scatteringAlbedoProperty;
const float m_maxExtinction;
const int m_extinctionProperty;
};
rendering of such clouds using today’s hardware, in reality productions may not be able to afford the
render times associated with hundreds of bounces. Approximation techniques are thus still useful and
often required. A recent technique which we call contrast approximation or contrast control (Wrenninge
et al. 2013) offers a useful way to simulate higher order scattering effects in an art directable fashion.
This technique of lowering the scattering coefficient σs by an extinction multiplier a can be easily added
to the Transmittance method of the multiple scattering integrators. Combining this with ideas from
(Wrenninge 2015), we have found that by exposing the current ray depth i to the volume integrator
(which we would need to make available from the lighting integrator), we can make use of the adjusted
scattering coefficient ai σs ; this is computationally inexpensive and results in only a single parameter to
adjust.
Fig. 19. Multiple scattering in clouds (highly anisotropic media). Left: 2 bounces of multiple scattering; center: 4
bounces of multiple scattering; right: 6 bounces of multiple scattering.
3.8 Emission
In the previous discussion, we have deliberately ignored the topic of emission and have assumed that
we are dealing with volumes whose absorption coefficient σa = 0, and thus σt = σs . We have thus been
parameterizing the volumes only with the extinction coefficient σt and the scattering albedo α.
For the tracking approach to integration, we can partially reintroduce emission into the implementa-
tion of SingleScatterHomogeneousVolume by adding the absorption coefficient σa (xt ) and volume
emission color Le (xt , ω) as parameters to the constructor. We have been picking values of t 0 for a
scattering location based on σt ; we can continue to use the same approach to determine the distance
traveled by a photon before it is either absorbed or scattered, since this continues to be based on σt .
After choosing t 0 we perform the extra random choice to determine the type of collision event that
occurred there, using Pa (x) = σσat as shown in equation 17:
Listing 16. Extra step in homogeneous single scattering integrator to deal with emission
// Compute sample location for scattering or absorption, based on the PDF
// normalized to the total transmission
float xi = rs.GenerateRandomNumber();
float collisionDistance = -logf(1.0f - xi * (1.0f - transmittance.ChannelAvg())) /
m_extinction.ChannelAvg();
For the PDF approach to integration, listing 13 can be extended by considering the absorption integral
∫d
t =0
T (t)σa (xt )Le (xt , ω)dt separately from the scattering integral. The T (t) component of the integrand
is already computed when constructing the discrete PDF for single scattering. If we assume that σa (xt )
and Le (xt , ω) are both relatively cheap to compute (because they are both simply properties of the
volume) then we may as well compute the answer to the absorption integral by using quadrature
instead of computing a PDF: there are no expensive terms that need approximation, and the quadrature
calculation for absorption can take place at the same time as the construction of the scattering PDF.
Unfortunately, this is not a complete implementation of absorption. The in-scattered radiance Ls in
the VRE also must take into account the light emitted by the volume itself (as well as all other emitting
volumes in the direction of ω 0), and we are missing this contribution. In fact, the direct lighting on
all other geometry in the scene must be augmented by the Le coming from volumes, considerably
complicating matters.
One approach to this problem is to augment the volume interface with an Emission method, which
is similar to the Transmittance method but instead of returning the transmittance, it must return an
estimate of the emitted radiance between two points. Once we have such a method on all volumes,
then in the same way that the implementation of the RendererServices’s GenerateLightSample
and EvaluateLightSample must be augmented to call the Transmittance method of any volumes
along the transmission ray, we can similarly require that an additional call to Emission be made to
any volumes in order to gather the emission. This emission is added to the L radiance returned by the
RendererServices methods. This ensures that emitted radiance is correctly accounted for in direct
lighting, while the change to the integrators similar to that shown in listing 16 handles the emitted
radiance for indirect lighting.
There is still one more additional wrinkle if we consider renderers whose implementation of Render-
erServices::GenerateLightSample involves importance sampling of lights. In the case of volumetric
emission, the volume is essentially a light source and may itself need to be considered during the
importance sampling. Consider the case where a scene is illuminated by fire or explosive effects; in
order to reduce noise, the sampling of lighting for direct illumination should importance sample the
emission function of the volume, as well as potentially the transmittance to the volume. One approach,
particularly useful when the volume is heterogeneous, is to voxelize the light emission distribution; for
further discussion, see (Villemin and Hery 2013). In the absence of such functionality, the substitution
of light sources in the middle of the volume solely for the purposes of "steering" the light importance
sampling may be required, and has certainly been used in recent production rendering.
Production Volume Rendering • 51
д
Fig. 20. A low density volume (green triangles, σt ) overlapping a high density volume (red hexagons, σtr ). The
д
chance of collision with either volume is the sum of the extinction coefficients σt + σtr . If a collision occured, the
д
σt
chance that the collision was with the green volume is д .
σt +σtr
One solution this problem is to choose a single primary volume integrator, which has full access
to the properties of all other volumes which coexist over the interval, and is responsible for a single
result which takes into account all properties of the overlapping volumes. To pick the single integrator
correctly, we require a priority scheme for these overlapping volume integrators. A simple homogeneous
absorption-only volume integrator cannot be trivially extended to deal with heterogeneous scattering,
whereas a heterogeneous integrator can correctly deal with the absorption-only integrator while
integrating its own results. In essence, the priority scheme ranks more capable integrators higher than
less capable integrators, and is used by Ray::GetVolume to pick the most capable integrator from the
list of volumes: the implementation in listing 5 is altered to find the most recently entered volume with
sufficient priority that can handle all other volumes.
Once we select a single integrator, we need to expose a list of properties from the Volume interface
necessary for an integrator to be able to perform a summed integration. Consider one of the scattering
heterogeneous integrators, which implement delta tracking. In the combined case, delta tracking would
require the sum of the maximum extinction coefficients in order to take the delta tracking step, and the
sum of the extinction coefficients at the potential interaction location. Each volume therefore needs to
expose the ability to query the maximum extinction coefficient and the local extinction coefficient.
Once a scattering location has been chosen, the transmittance can be computed using the summed
extinction properties of each volume. Now we need to resolve how to deal with scattering in the
combined volumes. By appeal to the non- interacting particle model, we can simply decide that the
collision event has occurred with a single particle from a single volume, and the only question is deciding
which volume. The probability of interaction with a volume is simply the extinction coefficient of that
volume divided by the sum of the extinction coefficients of all the volumes. Therefore, we only need
to build a CDF from the scattering coefficients and use a random number to pick one of the volumes.
Once we have picked a volume, a phase function from that volume can be used which abstracts away
all further details of the scattering away from the volume integrator — in essence, the integrand of the
in-scattering integral in equation 7 is now restricted to a single volume.
The following listing shows a modified version of SingleScatterHomogeneousVolume which can
account for other overlapping homogeneous volumes. Note the changes to the Volume interface: the
Production Volume Rendering • 53
addition of the CanOverlap and GetOverlapPriority methods, along with a list of common property
accessor methods. We assume that heterogeneous volumes have an overlap priority greater than one. The
lighting integrator is now responsible for creating instances of all Volume over the list of all Materials
on the ray and storing them on the shading context, so that ShadingContext::GetAllVolumes can
return them. A render demonstrating the correct overlapping behavior is shown in figure 21.
Listing 17. Single scattering homogeneous integrator extended for overlapping volumes
cclass SingleScatterHomogeneousVolume: public Volume {
public:
SingleScatterHomogeneousVolume(Color &scatteringAlbedo, Color &extinction,
ShadingContext &ctx) :
Volume(ctx), m_scatteringAlbedo(scatteringAlbedo), m_extinction(extinction) {}
virtual bool Integrate(RendererServices &rs, const Ray &wi, Color &L, Color
&transmittance, Color &weight, Point &P, Ray &wo, Geometry &g) {
if (!rs.GetNearestHit(Ray(m_ctx.GetP(), wi.dir), P, g))
return false;
// Sum the extinction over all volumes. Build a CDF of their densities
float distance = Vector(P - m_ctx.GetP()).Length();
std::vector<Volume*> &volumes = m_ctx.GetAllVolumes();
std::vector<float> cdf;
Color summedExtinction(0.0);
for (auto v = volumes.begin(); v != volumes.end(); ++v) {
summedExtinction += (*v)->GetExtinction();
cdf.push_back(summedExtinction.ChannelAvg());
}
for (auto f = cdf.begin(); f != cdf.end(); ++f) {
*f /= summedExtinction.ChannelAvg();
}
// Compute direct lighting with light sampling and phase function sampling
BSDF *phaseBSDF = volumes[index]->CreateBSDF(m_ctx);
L = Color(0.0);
Color lightL, bsdfL, beamTransmittance;
float lightPdf, bsdfPdf;
Vector sampleDirection;
rs.GenerateLightSample(m_ctx, sampleDirection, lightL, lightPdf, beamTransmittance);
phaseBSDF->EvaluateSample(rs, sampleDirection, bsdfL, bsdfPdf);
L += lightL * bsdfL * beamTransmittance * rs.MISWeight(1, lightPdf, 1, bsdfPdf) /
lightPdf;
weight = Color(1.0);
wo = Ray(P, wi.dir);
return true;
}
virtual bool CanOverlap() const { return true; }
virtual int GetOverlapPriority() const { return 1; }
virtual Color GetExtinction() const { return m_extinction; }
virtual Color GetScatteringAlbedo() const { return m_scatteringAlbedo; }
virtual BSDF* CreateBSDF(ShadingContext &ctx) const { return new
IsotropicPhaseBSDF(ctx); }
virtual Color Transmittance(RendererServices &rs, const Point &P0, const Point &P1) {
float distance = Vector(P0 - P1).Length();
return Color(exp(m_extinction.r * -distance), exp(m_extinction.g * -distance),
exp(m_extinction.b * -distance));
}
protected:
const Color m_scatteringAlbedo;
const Color m_extinction;
};
Production Volume Rendering • 55
Fig. 21. Two overlapping single scattering homogeneous volumes. Each volume has a different density, scattering
albedo, and phase function. The use of random selection based on a CDF built using each volume’s local extinction
coefficient correctly accounts for each volume’s different scattering properties.
A problematic situation arises when the camera is itself inside a volume, such as would happen in an
underwater scene. In the system described so far, we only consider a volume to exist when a ray hits
a piece of geometry with outward facing normals. There is no such geometry to intersect when the
camera is inside the volume, and we must add a special case to deal with this situation. At minimum,
user intervention is required to specify a volume-capable Material bound to the camera itself; all rays
originating from the camera are now immediately tagged as having entered the material as soon as
they are fired. A similar situation exists for bidirectional path tracing when tracing rays originating
from the light that are inside a volume.
Our discussion of overlapping volumes was inspired by the treatment of nested dielectrics by Schmidt
and Budge (2002), which describes a system for rendering refractive objects within each other. In fact, a
system which implements index of refraction tracking and intersection priorities as described in that
paper can be easily extended to track volumetric materials: a fish inside water contained within glass
can be robustly rendered with volumetric scattering (the thin body of the fish), and with absorption
(liquid and glass), while correctly tracking the relative indices of refraction at each interface, and not
suffering from precision problems at the geometric boundaries.
However, when rendering overlapping volumes which have identical scattering properties, and which
do not require boundary effects (i.e. they use a TrivialBSDF from listing 4), our system suffers from
performance problems as compared to the case of the equivalent single non-overlapping volume. To deal
with two overlapping volumes, we require three separate intervals of volume integration: two intervals
have only one volume, while the third has two overlapping volumes. Our simple single scattering
integrators always guarantee a lighting estimate at each interval, so we have now effectively tripled the
cost of direct lighting by creating three intervals. On top of this, the cost of dealing with overlapping
volumes requires density evaluations in each volume, even if we can get away with only integrating
and lighting one of them. The situation grows rapidly worse with many overlapping volumes. Section 6
describes a system for dealing with this particular case.
56 • Julian Fong, Magnus Wrenninge, Christopher Kulla, and Ralf Habel
Fig. 22. A scene from Finding Dory (2016) involving nested dielectrics and volumes. Dory’s material includes a
volumetric single scattering component. Hank’s subsurface scattering also took place in a volumetric framework
similar to that described in this chapter.
Production Volume Rendering • 57
4 OPTIMIZATION
4.1 Multiple sampling
Like any other compute-intensive problem, renderers can derive large speed gains by taking advantage
of locality of reference. The benefit of locality can be achieved in multiple domains: on-chip cache,
main memory, or disk. This becomes very important when dealing with complicated volume assets that
may involve gigabytes of voxel data. Even highly optimized routines for organizing access to this data
benefit from coherent access patterns.
In terms of locality, the tracking approach for heterogeneous volumes are much worse than the PDF
approach: the use of the majorant allows the tracker to skip over large parts of the volume, which leads
to more random access patterns. Even in a rendering architecture which batches rays for shading, the
number of steps taken by each ray can vary significantly and the integrator can often end up having to
finish single rays that take more steps than its siblings in the same batch.
We can at least improve locality significantly in the single scattering integrators by taking more
than a single estimate of the direct lighting. Both the tracking and PDF implementations in section 3.6
can be easily extended to add up multiple samples of direct lighting over a single volume interval, and
divide by the number of samples taken for a higher quality estimate of in-scattered radiance. This will
almost certainly be faster than firing the equivalent number of rays from the camera: the integrator can
calculate the distance to the end of the volume interval by firing a single ray, and the locality of access
to the volume texture will be improved significantly. The PDF approach to single scattering benefits the
most from taking multiple samples, since the high cost of building the discrete PDF can be amortized
over multiple samples in the volume.
In the case of the multiple scattering integrator described in section 3.7, the volume integrator is
unable to trivially perform multiple sampling as it cannot return multiple hit points to the light integrator.
In practice, we wouldn’t want to do this anyways; in our system, we imagine that the light integrator
would have its own set of rules governing how many indirect rays to spawn, and in practice this may
involve a set of heuristics such as ray depth, usage of Russian roulette, etc., not all of which should be
exposed to the volume integrator.
However, for many scenes, it is well worth considering a hybrid between the single scattering
integrators and multiple scattering integrators. It is often the case that the first few bounces of light
in a volume are the most important, and we want to focus more computational resources onto those
bounces for a higher quality estimate of direct lighting. After those first few bounces, however, the
relative importance of each additional path becomes less important to the eye and it is more important
to take faster, lower quality estimates of direct lighting.
The multiple scattering integrators we have described so far make no estimate of the in-scattered
radiance, preferring only to return the next hit point to the light integrator. If we instead alter the
multiple scattering integrator’s Integrate routine to selectively perform an estimate of the in- scattered
radiance — in effect, combining their implementation with the single scattering integrators — then in
conjunction with the lighting integrator, the integrator has now delivered a higher quality estimate of
the direct lighting. We would need to augment our interfaces to the integrator to deliver the current ray
depth or perhaps the current throughput to the eye, in order to allow the volume integrator to perform
this extra computation only when it is important to do so.
Note there is now a new complication: the multiple scattering integrator and the lighting integrator
are both computing direct lighting, and we are now injecting too much radiance into the system unless
extra steps are taken. As the weight calculated by the volume integrator was used to correctly scale the
contribution of both the direct and indirect contributions calculated by the light integrator, we need to
58 • Julian Fong, Magnus Wrenninge, Christopher Kulla, and Ralf Habel
separate this weight out into two separate terms: a new term to scale the lighting integrator’s direct
lighting contribution, and the old term still used to scale the lighting integrator’s indirect lighting.
4.2.1 Uniform sampling and MIS. A drawback with tracking methods is that their PDF is proportional
to the transmittance T (t) of a volume with unbounded interval 0 ≤ t < ∞. In practical terms, this
means that SingleScatterHeterogeneousVolume, which implements delta tracking, is highly unlikely
to terminate in a bounded volume when σt is low. For such low density volumes, this leads to very
high variance in the estimate for direct lighting, particularly when the volume is lit by a very bright
light source. Compare this to SingleScatterHomogeneousVolume, which will always find a scattering
location in the volume because the PDF is normalized to the total transmittance over the volume T (d)
and can thus be perfectly sampled.
Because it is the transmittance-based PDF which is the source of the problem, we look for an alternate
sampling strategy to use. The simplest such strategy is uniform sampling (sometimes referred to as
distance sampling): simply pick a random t where 0 ≤ t < d. We have avoided this strategy for
homogeneous volumes because it is almost always inferior to density sampling when σt is constant,
but as a fallback mechanism for sparse heterogeneous volumes it is useful. We also introduce it here as
a way to bring multiple importance sampling (MIS) (Veach 1997) into our discussion. We have already
been using MIS to combine samples from both the phase function and the light source during direct
lighting; because we now have two sampling strategies for t to consider, and it may not be clear which
one is preferable, we can instead just use both strategies simultaneously and combine the results with
MIS. (In practice, if the lower bound of the density over the volume is known, we can avoid MIS and
switch over to uniform sampling when the lower bound of the density is below some threshold. This
ties into the general discussion of generating bounds for tracking methods in section 4.4.2.)
To perform MIS between uniform sampling and delta tracking, we note that the PDF for uniform
sampling is simply:
( 1
if 0 ≤ t < d
pu (t) = d (30)
0 if t ≥ d
The PDF for delta tracking is essentially given by equation 14: pt (t) is the product of σt (t) and T (t),
the latter of which is estimated by delta tracking itself.
The standard MIS approach to blending samples requires the computation of a weight for each
sample, which requires calculation of the PDF p(t) for every technique. Consider the case of drawing
one sample for uniform sampling at location tu , and one sample by delta tracking at location tt : we
need to calculate pu (tu ), pu (tt ), pt (tu ), and pt (tt ). The complication here is the need to compute two
PDFs for delta tracking: pt (tu ) and pt (tt ). Rather than performing two separate invocations of delta
tracking in order to estimate the two transmittances T (tu ) and T (tt ) necessary for the PDFs, we can
estimate both transmittances in a single delta tracking invocation using a priori knowledge of tu as
follows: if delta tracking proceeds past t > tu (and thus has not found a location tt ) then T (tu ) = 1. If
Production Volume Rendering • 59
delta tracking stops at a distance tt < tu , then we can T (tu ) = 0. If delta tracking terminates because
t > d, then T (tu ) = T (tt ) = 1.
This technique of combining delta tracking with another importance sampling metric is broadly
applicable; for example, we can replace uniform sampling with equiangular sampling as described in
the next section. Note that in order to perform delta tracking to provide both transmittance estimates,
we require knowing the location of the other sample first.
A modification of SingleScatterHeterogeneousVolume to perform MIS is shown below.
do {
float zeta = rs.GenerateRandomNumber();
t = t - log(1 - zeta) / m_maxExtinction;
if (t > distance) {
break; // Did not terminate in the volume
}
Pl = P0 + t * wi.dir;
m_ctx.SetP(Pl);
m_ctx.RecomputeInputs();
weight = Color(1.0);
wo = Ray(P, wi.dir);
return true;
}
4.2.2 Equiangular Sampling. The general volume rendering equation is not easy to reason about
because it contains many non-analytical integrals. We simplify the problem by focusing on the case with
Production Volume Rendering • 61
the fewest number of integrals, single scattering from a singular point light source in a homogeneous
medium. Rewriting Equation 9 we obtain:
∫ b √
Φ
σs e −σt (t +∆+ D +t ) 2 2 dt
2 2
L(x, ω)
® = (31)
a D +t
Figure 23 describes the involved parameters. Note that to simplify the notation, we omit the inclusion of
visibility and phase function in the equation. We also reparameterize t so the origin is at the orthogonal
projection of the light onto the ray. This change modifies the integration bounds a and b (which can
be negative) and adds an extra term ∆ which is the distance between the real ray origin and the new
one. The use of integration bounds a and b is also convenient when dealing with spotlights as we can
restrict integration only to the part of the ray that intersects the light’s cone.
θb
θa r
D
a
∆ t
b
While the transmission term is bounded by 1, the incoming radiance Φ/r 2 presents a weak singularity
that starts to dominate as rays approach the light source. This reveals why distance sampling (distributing
samples proportionally to e −t σt ) can be suboptimal. Distance sampling focuses most samples close to
the viewer, missing the visually important light source (see Figure 24). In fact, the results for distance
sampling can be made almost arbitrarily bad by increasing σt , pushing the sample points closer to the
viewer and away from the light.
We can importance sample proportionally to the 1/r 2 term instead to focus more samples where
the incoming light is strong and cancel out the weak singularity directly. This results in a Cauchy
distribution which has the following normalized pdf and associated sampling function over the interval
[a, b] (ξ is a random number in [0, 1)):
D
pdf(t) = (32)
(θb − θ a )(D 2 + t 2 )
t(ξ ) = D tan (1 − ξ )θ a + ξθb (33)
θx = tan−1 x/D (34)
Equation 33 reveals that this technique linearly interpolates the angle between the bounds of integration,
so we refer to this technique as equiangular sampling. The results in Figure 24(b) show the dramatic
improvement compared to distance sampling. Due to the smoothness of the transmittance term, the
noise present using our method quickly vanishes and yields nearly noise free images with as few as 16
paths per-pixel.
62 • Julian Fong, Magnus Wrenninge, Christopher Kulla, and Ralf Habel
Fig. 24. Point light source in homogeneous media (16 paths/pixel, each method rendered in 2 seconds)
It should be noted that the equations above still contain a singularity when D = 0. This corresponds
to the case where the viewing ray passes through the point light exactly. While this may seem like a
corner case that could be ignored, it can occur in the common "flashlight" setup where a point light
source is parented to the camera. To solve this case we can use the following specialization:
ab
pdf(t) = (35)
(b − a)t 2
ab
t(ξ ) = (36)
b + (a − b)ξ
4.2.3 Equiangular Sampling from Area lights. It turns out that the scheme above generalizes very
well to area lights. Even though the integral over a light’s area is more complicated, the solid angle
subtended by the light source varies as 1/r 2 . Therefore, if the renderer supports solid angle sampling
from a point towards the light source, it suffices to choose a point along the ray using equiangular
sampling first as in the point light case, and then applying the solid-angle sampler from the chosen
point.
The original description of equiangular sampling (Kulla and Fajardo 2012) gives another strategy
for arbitrary lights that do not have convenient solid angle based importance sampling schemes. One
can still benefit from equiangular sampling by first choosing the point on the light source (which is
independent of the ray being traced) and then applying equiangular sampling from this chosen point. In
practice however, this approach is always inferior to schemes that can importance sample the solid angle
of the light source directly. We would therefore recommend investing the time in such samplers (Ureña
et al. 2013).
4.2.4 Equiangular sampling in Heterogeneous media. The last generalization we must discuss is how
to handle heterogeneous media. The presence of an integral for transmittance requires the use of the
techniques from section 3.6. The basic idea is to store a representation of the transmittance along the
viewing ray such that we may evaluate the transmittance at any point along the ray. This in turn means
Production Volume Rendering • 63
we can choose points along the ray freely and thus combine heterogeneous media with equiangular
sampling.
A particularly simple way (though not necessarily the most efficient) to achieve this is the classic
ray marching algorithm (Perlin and Hoffert 1989). The ray is divided into shorter segments over which
we can assume the medium properties are locally constant. This produces a piecewise exponential
representation of the volume that can be quickly evaluated at any distance t along the ray via binary
search. This means that we only need to march along the ray once and then can perform as many
lighting calculations as needed (taking multiple samples per light, or evaluating multiple light sources).
Because the computation of transmittance being decoupled from the lighting calculations, this technique
was called decoupled ray marching. It should be noted that this technique may be used with the unbiased
tracking methods presented in the previous section.. The important point is that transmittance can be
cached, and subsequently evaluated.
When dealing with lights that are both inside and outside the volume, neither equiangular sampling or
transmittance based sampling may be optimal on their own. Equiangular sampling works when close to
the light source while transmittance based sampling works well for lights outside the volume. Multiple
importance sampling (Veach and Guibas 1995) is a natural way to combine equiangular sampling with
density sampling (see Figure 26). As explained above, binary search can also be used to importance
sample from the representation of transmittance computed during the initial ray march.
Fig. 25. Heterogeneous medium rendered using decoupled ray marching (16 paths/pixel, ~5 min). Previous stochas-
tic methods would have a hard time capturing single scattering from the light sources embedded in the medium
as seen in Figure 24.
The biggest drawback of using classical ray marching is that it introduces a bias in the calculation.
When working with voxel based volumes, the bias is not noticeable because the step size can be fixed to
be on the order of a single voxel. However efficiency suffers because any homogeneous regions still
perform many lookups. The more recent work of Novák et al. (2014) can instead be used to obtain a fully
unbiased algorithm. The residual ratio tracking method (see Section 4.4.1) creates a similar piecewise
exponential representation for transmittance and can be mostly used as a drop-in replacement. It should
be noted that the original method does allow importance sampling proportionally to σs (xt )T (t) while
unbiased methods only support sampling proportionally to T (t).
64 • Julian Fong, Magnus Wrenninge, Christopher Kulla, and Ralf Habel
Fig. 26. Closeups of Figure 25. MIS combines the strengths of each line-sampling technique.
sampling position along the entire path. This requires additional bookkeeping, but one can build a single
discrete cdf representing all the scattering segments encountered along a path. To lower variance, the
first and last segments can be always integrated, while all intermediate segments can perform a single
lighting calculation. One can also employ splitting and perform multiple lighting calculations across
the entire path, but then care should be taken that the number of segments being sampled is larger than
the number of samples requested. The exact cross over point where this technique pays off is highly
implementation dependent.
K
Ö σt (xi )
T (t) = 1−
i=1
σ̄
Ratio tracking can easily replace an implementation of delta tracking, such as the implementation of
Transmittance method for BeersLawHeterogeneousVolume, which follows algorithm 3.
Ratio tracking can also be used in the implementation of Integrate of single scattering heterogenous
volumes (listing 10). The location used for direct lighting remains unchanged from the delta tracking
implementation (the first potential interaction), but instead of terminating at the first step, we can
continue until the end of the volume, accumulating the transmittance as above. Ratio tracking can
also be easily combined with other importance sampling techniques such as equiangular sampling to
improve the estimate of transmittance, and is a straightforward replacement for delta tracking’s usage
in multiple importance sampling (see section 4.2.1).
While ratio tracking delivers a much better estimator of the transmittance than delta tracking, unlike
delta tracking it must also track all the way through the volume, and must evaluate the extinction
coefficient at every step. This means it is a higher cost estimator than delta tracking, especially in
volumes with a high majorant of extinction. This cost can be greatly mitigated if we can tolerate a slight
bias: terminating the ratio tracking if some arbitrarily low transmittance is reached. Even so, this leads
to the question: is it faster to converge to take a higher number of lower quality delta tracking estimates,
or a lower number of higher quality ratio tracking estimates? We have generally found in production
that the latter is true, especially when the extinction lookup is expensive and can benefit from locality
of execution.
Residual tracking is another incremental improvement that increases the accuracy of the transmittance
estimator. Residual tracking introduces a control extinction coefficient σc which is constant over the
volume, and ideally is very similar to the actual extinction coefficient σt . With σc , the transmittance
T (t) is now broken into two parts: a control transmittance Tc (t), which can be written in closed form,
and a residual transmittance Tr (t), which must be estimated:
Tc (t) = exp(−σc t)
∫ t
Tr (t) = exp − σt (xs ) − σc ds (37)
s=0
T (t) = Tc (t)Tr (t)
By applying the ratio tracking estimator to Tr (t) we arrive at the combined technique of residual
ratio tracking, with resulting pseudocode shown in algorithm 4. The key improvement of residual
ratio tracking over ratio tracking is the use of σ̄r , the majorant over the residual extinction coefficient
σr = σt − σc . As long as σ̄r is smaller than σ̄ , the mean free length of the steps between tentative
collisions is lengthened, and residual ratio tracking will correspondingly evaluate the extinction with
less frequency.
Novák et. al describe three different choices for the control extinction coefficient σc , and also describe
that while the theoretical best choice is the average over σt , this may result in certain situations which
lead to increased variance. We have found in practice it is best to avoid these situations and use the
minimum value (or minorant) of σt . This is the chief drawback of residual ratio tracking: the need for
the minorant as well as the majorant of the extinction coefficient. In the next section, we will discuss
acceleration structures for tracking which can also be used to return the minorant of the extinction
coefficient. Finally, we note that in practice, residual ratio tracking can be used for implementations
of Transmittance, but are not as straight forward to use for single scattering implementations of
Integrate; the control transmittance must be taken into account when selecting a location for direct
lighting.
Fig. 27. Transmittance through heterogeneous but low variance volume. Left: delta tracking; center: ratio tracking;
right: residual ratio tracking. Bottom row images are zoomed by 10 x.
4.4.2 Acceleration structures for tracking. While tracking methods can be very attractive due to being
unbiased techniques which require low overhead, they have one major disadvantage: in order to remain
unbiased, the initial tracking step size must be calculated from the maximum extinction coefficient σt
of the volume. If the volume has a very heterogeneous σt , the majorant of σt over the volume may be
far higher than the average value of σt in many places. For example, consider a mostly homogeneous
volume of very low density which is dominated by a "spike" in density, as shown in figure 15. This
high maximum density would cause the initial tracking step size to be small. Since the actual density
sampled at the step would more likely than not be small compared to the maximum density, the chance
68 • Julian Fong, Magnus Wrenninge, Christopher Kulla, and Ralf Habel
of interaction with the volume itself would also be small. Over many rays, this would result in a large
number of steps taken on average. Since every step requires a computation of the actual density, on
production scenes these per-step density calculations will be the dominant cost of volume rendering.
To ameliorate this problem, we can break up the volume into smaller, non- overlapping subregions,
and bound σt inside each region. Subregions with a high σ̄ would be sampled at the appropriate higher
initial stepsize, while subregions with low σ̄ would be sampled at the lower densities. In effect, by
doing this, denser regions of the volume are sampled by the tracking method with the appropriate
higher frequency, while less dense regions are sampled less often. However, dividing the volume up
into subregions means that the region of volume integration along the ray is no longer a single interval:
the ray which formerly intersected a single volume region now intersects multiple non- overlapping
subregions to create multiple subintervals, each subinterval having its own σ̄ . We must determine the
intersection of the ray against these subregions, and we must be able to do so quickly. One convenient
and well-studied approach to this problem is to use a k-d tree (Bentley 1975) to spatially subdivide the
volume region into subregions; this approach was first suggested for the acceleration of delta tracking
by Yue et al. (2010). The leaf nodes of the k-d tree store the maximum density of a single subregion. We
can then intersect a ray against the k-d tree to come up with the list of overlapping volume subregions;
these regions divide the extent of the ray into subintervals, each with an associated σ̄ value.
Fig. 28. A heterogeneous volume with a spike in density results in a high σ̄ everywhere, requiring many short
tracking steps and many evaluations of the extinction coefficient (left). Dividing the volume with a kd-tree lowers
the majorant in large regions, resulting in many fewer evaluations (right).
With a well-constructed k-d tree, the dominant cost of rendering a heterogeneous volume when using
a tracking method is now no longer the per- step evaluation of σt ; it instead shifts to the intersection
of the ray against the k-d tree in order to find the list of subregions which intersect the ray. This is
very much analogous to the inner workings of a ray tracer: we avoid the costs of many per-geometry
intersection tests by using a ray acceleration data structure. A simple stack-based traversal algorithm
such as the one published by Jansen (1986) works well here, and can be reasonably optimized by using
tail recursion, and by reducing the memory usage of each node (for example, by using an implicit
Production Volume Rendering • 69
representation which only stores the split plane, and avoiding explicit pointers to the children nodes).
For a more general overview of k-d tree traversal algorithms, please see (Hapala and Havran 2011).
While a well optimized implementation of k-d tree traversal is important, the details of the construction
of the k-d tree are just as important, as reported by Yue et al in their follow-up paper (2011). A naively
implemented k-d tree can offer a tremendous speedup compared to the non accelerated implementation,
but a well-tuned k-d tree can offer several times speedup on top of that. We will depart somewhat
from (Yue et al. 2011) and focus instead on a well researched heuristic for building k-d trees, the Surface
Area Heuristic (SAH) (MacDonald and Booth 1990), which is commonly used for building k-d trees
used for ray intersection against geometry. In brief, this heuristic tries to minimize the recursive cost
function C(V ), defined for a non-leaf node V of the k-d tree as follows:
SA(Vl ) SA(Vr )
C(V ) = KT + C(Vl ) + C(Vr ) (38)
SA(V ) SA(V )
where KT is the cost of a traversal step through the k-d tree, SA(V ) is the surface area of V , Vl is the
left subchild of V and Vr is the right subchild of V . When dealing with geometry, the cost function of a
leaf node C(V ) would normally be a simple function of the number of triangles in the leaf node. As we
are interested in minimizing the number of delta tracking steps in the volume, a more useful yet also
simple cost function is
K D diag(V )σ̄ (V )
C(V ) = (39)
− log(0.5)
where K D is the cost of evaluating σt somewhere in V , diag(V ) is the length of the diagonal of the
volume V and σ̄ (V ) is the majorant of σt over V . This cost function can be understood simply as the
maximum number of delta tracking steps taken in the volume assuming the chance of termination
at every step is zero, which is the diagonal of the volume, divided by the length of the average step
− log(0.5)
σ̄ . This cost function can be further improved by removing the zero-termination assumption,
and instead taking into account the conditional probability of termination, which at every step is the
average value of σt divided by σ̄ in V .
Because equation 38 is a recursive function, minimizing it over all possible subtrees is a very expensive
problem to solve. The usual simplifying assumption is to use a greedy algorithm which at each step
computes only an approximation to C(V ) rather than recursing: it assumes that when computing the
cost of C(V ), the cost of the subvolumes C(Vl ) or C(Vr ) can be approximated by assuming they are leaf
nodes, thus allowing the use of equation 39 as their cost, leading to a modified cost equation:
C(V ) = SA(Vl ) diag(Vl )σ̄ (Vl ) + SA(Vr ) diag(Vr )σ̄ (Vr ) (40)
In this formulation, the terms that are invariant for a volume can be dropped, since we are just interested
in minimizing the function locally in the greedy algorithm, and there is no longer a recursive aspect.
Now, instead of computing a globally optimal solution, we simply start at the top level volume V and
compute the splitplane which divides the volume V into two subvolumes Vl and Vr which minimizes
equation 40. We recurse over each subvolume until some termination metric is satisfied.
For more discussion on building SAH-optimized k-d trees, please refer to the overview by Wald et al.
(2006).
In order to calculate σ̄ over a subvolume, we must of course be able to compute the σt over the entire
subvolume. A typical approach to this problem is to voxelize the entire subvolume and run the full
pattern generation inputs in a prepass. If the finest possible resolution of the input to the extinction
coefficient calculation is known a priori — perhaps because the input is sourced from a simulation run
at some finite frequency — the voxelization can be set to this resolution, and the resulting maximum
70 • Julian Fong, Magnus Wrenninge, Christopher Kulla, and Ralf Habel
will be guaranteed to be correct. If however the input resolution cannot be determined in advance —
perhaps because some procedural shading will add additional advection to the volume at runtime —
the voxelization may miss some detail, which will result in biased results. In practice, this bias may be
acceptable, especially if the fine voxelization otherwise required would necessitate a high preprocessing
time. In either case, if a shading prepass is required, it is possible to intertwine the k-d tree construction
with an architecture which minimizes the in-memory requirements of shading: for example, using
a REYES-like architecture which splits and dices to grids of microvoxels, evaluates the shading over
the grid, and discards the grids. For very large volumes, however, this may come at a considerable
startup cost which will affect the time to first pixel of rendering. If it is known that shading will not add
additional detail to the volume (usually because σt is baked into a file), another approach is to bake
the maximum into the file format at runtime. This is useful because complicated volume simulations
are often written only once, but read multiple times over the course of their lifetime in production.
However, this baking step ideally requires knowledge of the k-d tree optimization employed by the
renderer. If the maximums are simply a coarser subsampling of the volume data, a refitting step may be
required by the renderer in order to create an optimal k-d tree.
We will not show how the pre-processing of the volume k-d tree takes place in our hypothetical path
tracer; we will either assume it is handled by an implementation of the Volume interface, or handled by
the renderer and provided by the RendererServices object. Furthermore, we assume that the facilities
for intersecting a ray against a k-d tree are also handled in one of these two places; the choice of which
is highly dependent on the implementation of shading in the system. We will simply assume that some
function intersectSegmentAgainstKDTree exists where a line segment denoting the region of volume
integration can be intersected against the k-d tree to produce a list of subinterval endpoints rangeDists
and their σt majorants maxDensities. With this information in hand, we need to modify our tracking
integration algorithms. The implementation of BeersLawHeterogeneousVolume::TrackingVolume
from listing 8 can be augmented by simply changing how the first delta tracking step takes place:
Listing 20. Delta tracking using bounded subintervals from a k-d tree
bool takeInitialStep(RendererServices &rs, RtInt rangeCounts, float const * rangeDists,
float const * maxDensities, float *accumDistance, int *currentSeg) {
bool finished = false;
do {
// Find first interesting segment
int i = *currentSeg;
float maxRayDensity = maxDensities[i];
// Skip over empty segments entirely
if (maxRayDensity == 0) {
if (i == rangeCounts - 1) {
// We're done with all the segments
finished = true;
break;
} else {
*accumDistance = rangeDists[i];
*currentSeg = i + 1;
continue;
}
}
Production Volume Rendering • 71
float xi = rs.GenerateRandomNumber();
// Woodcock tracking: pick distance based on maximum density
*accumDistance += -logf(1 - xi) / maxRayDensity;
if (*accumDistance >= rangeDists[i]) {
// Skipped past the end of the current segment
if (i == rangeCounts - 1) {
finished = true;
break;
} else {
// Went past the segments with no interaction. Move on to
// the next segment, resetting the accumulated distance to
// the beginning of that segment
*accumDistance = rangeDists[i];
*currentSeg = i + 1;
}
}
else
// Check for actual interaction
break;
} while (true);
return finished;
}
virtual void Transmittance(RendererServices &rs, const Point &P0, const Point &P1,
Color &transmittance) {
float distance = Vector(P0 - P1).Length();
Vector dir = Vector(P1 - P0) / distance;
bool terminated = false;
float t = 0;
int currentSeg = 0;
int rangeCounts;
float *rangeDists, *maxDensities;
intersectSegmentAgainstKDTree(P0, P1, &rangeCounts, &rangeDists, &maxDensities);
do {
if (takeInitialStep(rs, rangeCounts, rangeDists, maxDensities, &t, ¤tSeg))
break; // Did not terminate in the volume
terminated = true;
} while (!terminated);
if (terminated)
transmittance = Color(0.0f);
else
transmittance = Color(1.0f);
}
Fig. 29. The use of a k-d tree data structure to bound the majorant of σt results in a reduction in the number of σt
evaluations in this scene by over a factor of 6, which in this implementation reduces the runtime by over 30%.
In order to implement residual ratio tracking, we not only require the majorant of σt over a volume,
we need the minorant. This is a trivial extension of the pre-processing necessary to build the k-d tree,
except that the cost function needs to be modified. At the bare minimum, equation 39 would be changed
to reflect that the average step is lengthened by the minorant σqt (V ):
K D diag(V )(σ̄ (V ) − σqt (V ))
C(V ) = (41)
− log(0.5)
With knowledge of the minimum and maximum densities in subintervals over the extent of an
interval, we can perform several other very useful optimizations. First, if the σ̄ at every subinterval
is zero, we know that the beam transmittance of the entire volume interval is also trivially 1. This
is essentially an empty volume optimization, and can arise in practice if the volume loosely fills its
bounding box. Because this optimization can be significant, it is well worth ensuring that the k-d tree is
built to maximize regions of zero density. Second, we can use the minorant of σt over each subinterval
to compute a lower bound on the beam transmittance of the volume interval:
n
e −σ|t (i)d (i)
Ö
Tr ≤ (42)
i=1
Production Volume Rendering • 73
If we accept a slightly biased result and establish some minimum transmittance ϵ such that Tr ≤ ϵ
is considered an opaque transmittance, this condition can be used to skip a more expensive tracking
operation that would otherwise be incurred by the computation of transmittance.
74 • Julian Fong, Magnus Wrenninge, Christopher Kulla, and Ralf Habel
Fig. 30. Left: A volume with smeared motion blur. Note the change in light bleed. Right: The correct motion blur
computed using transformation motion blur
5 MOTION BLUR
5.1 The problem with motion blur
At a glance, motion blur in the path tracing context should be trivial. Time is simply another dimension
over which samples are distributed, and the accurate solution that handles all types of motion blur
is to simply let t = ξ for each ray. Given enough samples the resulting image will be imbued with
photorealistic motion blur and the goal will be accomplished. Although a gross oversimplification, this
rationale may be the underlying reason why motion blur often gets glossed over or ignored in the
rendering literature. In reality, the addition of time and deforming geometry in a rendering system
greatly complicates the implementation, effectively turning a (usually) tractable three-dimensional
problem into a four-dimensional engineering nightmare.
Note: In this chapter, we are considering deformation motion blur, meaning motion that varies within
an individual object. Transformation motion blur, by which individual objects are rigidly animated using
their transformation matrices, can be achieved identically for both geometry and volumes.
Volumetric motion blur is different from geometric motion blur in the fact that volumes lack the
topology that defines a geometric object. Whereas a surface renderer generally treats a deforming object
as the interpolation between two states (e.g. at the start and end of the shutter), a volume lacks the
scaffolding to do so. Instead, volumes are fields that describe the value of a function (usually density)
across space, and the only way to define motion is to assign a vector-valued motion field to the volume,
whose magnitude and direction describes the instantaneous velocity of the medium at any given point
in space.
t = 0.0
t = 1.0
Fig. 31. Two motion samples of a single microvoxel grid. Because the topology is identical, simple interpolation
can be used to find in-between states.
The technique of smearing voxel data eventually gave way to two improved techniques: microvoxel
motion blur and advection motion blur. The two methods fit in the two main rendering architectures at
the time: microvoxel motion blur fit well within Reyes-based renderers, and the Eulerian motion blur
method (sometimes also called advection motion blur) worked within the ray marching (i.e. ray tracing)
framework.
P1 – O1
P2 – O2
P3 – O3
P1 P2 P3
v3
v2
v1
Fig. 32. Eulerian motion blur, also called advection motion blur. Each sample point is offset by a motion vector by
a magnitude determined by the ray’s time value.
However, the method is only fully accurate for velocity fields that are not spatially varying. We can see
why if we consider a “curved” velocity field: It is not necessarily possible to take a step backwards from
P to P 0 = P − v(P), and then return to the original point by stepping forward along the velocity of the
new position, i.e. P , P 0 + v(P − v(P)). Intuitively this means that the material that we transported from
P 0 to P by tracing backwards along v(P) would actually have traveled to the point P 00 = P 0 + v(P 0).
The cost of Eulerian motion blur depends on two factors. First, there is an increased cost with each
sample taken, since both the velocity field and the density field must be evaluated. This tends to amount
to an increase of roughly 100% in the time spent computing density values, compared to just a single
density lookup. The second factor depends on the magnitude of the motion and how the acceleration
structures are designed. Similarly to microvoxel motion blur, the deformation aspect has to be taken
into account when performing any kind of empty space optimization during the ray traversal. For
example, if a superstructure that identifies empty space is constructed at t = 0, then a padding must be
applied so that even after deforming a lookup point, the empty space is accurate. This is equivalent to
displacement bounds in surface rendering, and can make volumetric acceleration structures much less
efficient, especially if the motion blur magnitude is large.
density
time
density
time
Fig. 33. Illustration of the temporal function stored in two temporal voxels. Note that the placement and number
of samples varies between the two.
When it comes to tracking integrators, having tightly bounded statistics on the extinction property is
absolutely key to good performance (even for integrators that don’t need a strict majorant), and both
microvoxel- and Eulerian motion blur make the problem intractable.
Fig. 34. Left: Volume with no motion blur. Center: Microvoxel-based motion blur. Note that the fluid source in the
upper right is incorrectly blurred. Right: A temporal volume renders faster and correctly handles the continuous
injection of density.
that each voxel now measures the fluctuation in density over time. Even though it captures no actual
motion, it is a perfectly valid representation of the physical state of the volume seen over time. In fact,
because the quantity and location in time of the sample points can vary from voxel to voxel, voxels do
not necessarily ever see the same “frame” of animation.
The rendering performance of temporal volumes is very predictable. Because the lookup cost is
independent of any motion apparent in the data, the only overhead compared to a non-temporal volume
is the additional interpolation of the one-dimensional function in each voxel. Although technically an
O(log N ) operation, the number of time samples is generally small enough that the speed impact seen in
density calculation is roughly 30%. On a production-scale shot with significant motion blur, the fact that
motion magnitude no longer affects render time may mean that a shot renders several times faster than
when using the Eulerian method. This is largely due to the fact that a temporal volume can produce
meta property calculations (i.e. min/max) that are tightly bounded, resulting in efficient acceleration
structures independently of visual motion blur magnitude.
Apart from rendering efficiency, temporal volumes have the advantage of being able to handle all
forms of motion blur, including curved motion as well as material appearing or disappearing during
the course of the shutter interval. The latter is especially useful for fluid simulations where density is
injected at high speed – see Figure 34.
In practice, there are multiple ways of generating temporal volume data. The original paper describes
the Reves algorithm, essentially “Reyes for volumes”, which is suitable for procedurally modeled volumes.
It also discusses how to generate temporal volume data given non-temporal volumes plus a velocity
field, in effect shifting the Eulerian motion blur method to a pre-computation step. Lastly, it is possible
to generate temporal volume data directly in a fluid simulator, by caching in memory each simulation
sub-step and reconstructing a full animation frame’s worth of temporal data once the simulation step is
complete. The latter version has the benefit of being able to capture intricate sub-frame motion without
affecting the final render time, which can be especially beneficial for fast-moving simulations such as
fire and explosions.
The temporal volume method has been used in multiple Pixar films, such as The Good Dinosaur
(Wrenninge and Rice 2016), Cars 3 (Marshall et al. 2017) as well as the upcoming Coco.
Production Volume Rendering • 79
6 AGGREGATE VOLUMES
6.1 Integration intervals
The traditional view of volumes in the rendering context is that each one lives in a box. This granularity
is, in a way, the first form of optimization in volume rendering: there is no need to perform calculations
in areas that are known to be empty. When volume rendering was performed using ray marching,
techniques such as empty space optimization (see Wrenninge (2012) for an overview) were used to
answer questions about the internal structure of the volume, such that the integrator could optimize
its calculations. The idea was that a volume could communicate to the integrator regions that needed
attention vs. regions that were known to be empty. Also, the step length of a ray marcher was tightly
coupled to the Nyquist limit, and it was important for each volume to communicate to the integrator its
frequency content. As such, the granularity of such queries were strictly in the hands of the volume
itself, and each volume could tell the integrator to divide the ray into an arbitrary number of integration
intervals.
class Volume
{
// ...
virtual void getSegments(const Ray &ray,
std::vector<Segment> &segs) const = 0;
// ...
};
In the case of ray marching, this was a reasonable arrangement: the empty space was often analyzed in
terms of the volumetric data structure itself, and both OpenVDB (Museth 2013) and Field3D (Wrenninge
2009) have built-in mechanisms for checking whether a given region of space is empty (i.e. unallocated).
Likewise, the sampling frequency (i.e. the voxel size) was known only to the volume itself.
Fig. 35. Gathering integration intervals from the blocks/tiles of a voxel buffer. The intervals are of uniform size
independently of the contents of the volume. Empty space can be culled by recognizing that max=0 for certain
intervals.
class Volume
{
// ...
virtual void getSegments(const Ray &ray,
std::vector<Segment> &segs) const = 0;
// ...
};
Fig. 36. Explicitly computing meta-properties along a ray involves checking each voxel that contributes to points
along the ray.
class Volume
{
// Query the maximum density along a ray segment with given width
virtual void getMaxDensity(const Ray &ray, float filterWidth,
float start, float end) const = 0;
// ...
};
1 This happens because the voxel sample is considered to lie in the center of the voxel
82 • Julian Fong, Magnus Wrenninge, Christopher Kulla, and Ralf Habel
Fig. 37. Efficient integration intervals for a cloud with uniform interior density. Only the short segments near the
boundary of the cloud require small steps by a tracking integrator.
A second observation to make is that the ideal granularity of the meta-properties vary within a
volume. For example, in a cloud, we would like the region around the edge to be as short as possible,
so that we can take large or no steps in the thin or empty area around the cloud, then quickly cross
the part where density goes from low-to high (which is where a Woodcock integrator would need to
take short steps and reject many null-events), then proceed into the thick part of the cloud where step
lengths again can be long, due to the minimum and maximum densities being close in range. Figure 37
illustrates the configuration.
With these in mind, we would ideally like to change the interface between the volume and the
integrator such that volumes can be more agnostic of the integrator’s design, and provide only a bare
minimum of operations such that the integrator can point sample at individual marching steps, and
query meta-properties at a granularity that is appropriate both for the integration method as well as
the global arrangement of volumes.
Fig. 38. Overlapping volumes create many short integration intervals (seen on top) if volume boundaries are
tracked explicitly. Even if each interval is nearly homogeneous and could use a long step length, the integrator is
forced to reset the tracking algorithm at each interval change, causing poor performance.
Volume A
Volume B
Volume C
Fig. 39. The aggregate data structure. Each node records a list of volumes that overlap (partially or completely) as
well as the min and max value of the contained volumes.
Fig. 40. Integration intervals gathered from the octree have boundaries at the octree nodes, not at the volumes’
interfaces. Thus, traversal complexity is independent of how many volumes are intersected by a given ray.
• Fast meta-property queries: The meta-properties can be computed once per region, with the cost
amortized across all subsequent rays that traverse the node. This dramatically decreases the cost
of querying meta-properties from the scene, even when constructing fine-grain representations
thereof.
• Integrator-agnostic volumes: The aggregate hides the exact bounds of the underlying volumes
from the integrator, and instead exposes a hierarchical structure that can be traversed linearly
without consideration of precisely where the underlying volumes’ interfaces lie. Thus, individual
volume never receive ray-specific queries. The volumes only need to respond to point sampling
(for the tracking) and range queries (for constructing the meta-property representation), which
simplifies the interface, improves efficiency while at the same time providing better meta-
information to the integrator.
• Volume-agnostic integrator: The aggregate also hides all the irrelevant properties of the un-
derlying volumes, such as their exact boundary location and the data structure used to store
them.
For a production renderer, we need to consider details such as per-sample time for motion blur and
filter width for texture filtering when sampling a volume. Nonetheless, the volume aggregate approach
requires a very small API to the volumes.
A simple (recursive) Woodcock-type integrator can then handle an arbitrary set of volumes in a
scene trivially. Because the aggregate hides the explicit structure of the scene and the iterator hides the
traversal, the resulting code remains concise.
Aggregate node
Padded region
Fig. 41. When computing min/max for a given aggregate node, we expand the region by the ray’s filter width in
order to get a conservative value. In order to limit the number of filter width queries stored at each aggregate
node, we round the value up to the nearest power-of-two.
Fig. 42. The spread between max and min converges as a given signal is low-pass filtered (e.g. in MIP mapped
volumes). The high resolution signal (red) is filtered at half frequency (green) and again at quarter frequency (blue).
This can be leveraged for min/max queries with a large filter width.
the heuristic may force excessive subdivision since the min/max delta remains high at each division.
However, if we have access to a properly filtered representation of the volumetric properties (e.g. MIP
mapped volume data), then we can compute the meta-property on data which is low-pass filtered, and
for which the spread between min and max is guaranteed to be narrower than for the full-resolution
data. By computing a unique set of meta-property values for multiple filter widths, as described above,
we avoid the problem of excessive subdivision.
this often occurs when small and low-density volumes are present. The aggregate may be requested to
insert a volume of density 10−4 and size 10 into a node of size 103 . The volume will not likely contribute
much to the image, but as far the integrator could tell, there is potentially density to find. However, the
small size of the volume means that nearly all samples taken in the node have zero extinction and force
the integrator to keep stepping.
A convenient solution to this corner case is to force subdivision of aggregate nodes that are larger
than the volume contained, regardless of the volume’s majorant extinction.
Fig. 43. 87 individual cloud pieces make up the cloudscape. 21 minutes (8 cores) at 1024 samples per pixel using 32
bounces of multiple scattering.
Table 2. Performance breakdown. Steps per camera ray and shadow ray indicates average number of steps. Rays
per second indicate the speed of individual pixel samples, including all indirect and shadow rays.
Integrator Bounces Time Steps / camera ray Steps / shadow ray Rays / second
Woodcock 1 2m 15s 15 11 2.9M
PDF 1 1h 14m 40s 182 118 87K
Woodcock 32 21m 36s 21 30 305K
PDF 32 8h 6m 10s 183 126 13K
approach will generally have better performance in this case where race conditions exists but are very
rare.
Fig. 44. Batch rendering pipeline with two sorting stages (left) and a large city data set rendered with Hyperion
(right) (Eisenacher et al. 2013).
While the volume rendering in Hyperion hooks into the streaming system, it does not use the sorting
mechanism. There might be possibilities to accelerate memory accesses in volumes, but the three-
dimensional nature of volume data sets in context of accesses along even coherent ray directions is
challenging. Hyperion uses the PDF approach, though a new system based on tracking is in development
as of 2017. The volume calculations are done before the ray batches are processed and any in-scattering
rays generated by the volume rendering put in the streaming batches and treated like any other ray.
92 • Julian Fong, Magnus Wrenninge, Christopher Kulla, and Ralf Habel
Fig. 45. A simple scene (left) and the positions of the cache points in the scene overlayed (right).
Preparing the Cache Points. In another pre-render step, we analyze each light for each cache point
(with some pre-culling to avoid unnecessary tests). For each light, we calculate the solid angle and
unoccluded irradiance incident to the cache point. For light primitives such as quad lights and sphere
lights we can use analytic expression to calculate the analytic irradiance. After culling unimportant
lights through a heuristic, the remaining lights are separated into lists, the nearby list and six distant
light lists for each cardinal direction (x,y,z and negative directions). All lights that have a large solid
angle from the position of the cache point go into the nearby light list. The reason to treat nearby lights
separately is because the irradiance is changing significantly in position and shading normal direction.
Lights that have been categorized to be distant lights are sorted into the 6 lists depending on their
contribution to the cardinal directions a light list represents. The light cache points directly store a
precomputed irradiance for each light. Any non-importance sampled lights are sampled along with the
BSDF sampling.
Once the light cache points are generated, a kd-tree is built to be able to query the closest cache
point efficiently during rendering. When a shading point queries for a light to sample, the nearest light
cache point evaluates the irradiance contribution of all the nearby lights. The corresponding cardinal
direction list depending on the shading normal is determined in order to generate weights for each light
in the combined lists. A PDF and CDF over the weights is then generated in order to determine the
light to be sampled for the shading point.
Production Volume Rendering • 93
On-line Visibility Learning. In addition to the light lists, the cache points also hold a visibility weight
for each light in the cache point. During rendering, a cache point keeps track of the ratio of successful
light hits to occluded hits and a heuristic includes this ratio into the weight calculations. The heuristic
is very conservative to avoid undersampling of highly occluded lights such as a sun light through a roof
with small holes.
Efficiency of Light Cache Points. In spirit, this approach is similar to (Georgiev et al. 2012) and (Vorba
et al. 2014) where an initial estimate is generated from a pre-pass which is then refined during rendering.
We see a lot of the same behavior described in these publications in Hyperion. At first, the image
converges slowly but once the quality of the visibility learning is high enough, the image converges fast.
Light cache points play an essential role to achieve good efficiency in complex production scenes.
Especially scenes with hundreds of lights and up have a significant speedup by several factors. Also
outdoor scenes where large parts of the scene is in shadow see huge performance gains as the shadowed
areas are identified by the visibility learning.
An additional advantage is that the integrator can keep track of contributions from different volumes,
so it is possible to write the per volume contributions into different frame buffers to separate them out
for compositing.
7.3.4 Building the In-scattering PDF. The transmittance calculation is very straight forward, the
intelligence and optimizations are almost all in building a high quality in-scattering PDF with moderate
computational cost. To build the PDF, we need to consider all volumes at the same time, but we have the
freedom to built it as conservative or aggressive as we need to. We use an adaptive ray-marching scheme
after the per volume transmittance that walks along the ray, heuristically determining the ray-march
step size and and weights from all available sources (volumes and acceleration structures, cache points,
etc.). We accumulate them in three separate PDFs in order to perform multiple importance sampling
between them to arrive at a high-quality PDF for in-scattering sampling.
Transmittance PDF. During the transmittance estimate, we already generated the data needed for the
transmittance PDF in the form of the cache that is used to avoid multiple transmittance estimates in
the integration. Therefore this PDF is not generated during the adaptive ray-marching step. We simply
need to normalize the cached transmittance estimate to produce the PDF.
Extinction/Albedo PDF. The second PDF is produced with the adaptive ray-marching stepping along
the ray. The acceleration grids inform about the homogeneity of the volumes on intervals along the ray,
besides detecting empty space. Heuristics decide if the density and albedo is probed on a finer level to
increase the quality of this PDF as deemed necessary. We also incorporate values looked up during the
transmittance estimate in the heuristics.
Light PDF. The third PDF is the heaviest to generate, we probe for the flux incident on a ray position.
This requires a nearest-point traversal on the light cache point kd-tree, making up for the bulk of cost
to generate this PDF. This PDF has similar properties to PDFs generated and sampled by equiangular
sampling of lights (Kulla and Fajardo 2012), but allows to integrate any kind of light sources. But due to
the kd-traversal, it takes much more resources than equiangular sampling.
7.3.5 Sampling the In-scattering PDF. To sample all three PDFs in the theoretically optimal way would
be to use product importance sampling, multiplying them and drawing a sample from the resulting
PDF. Unfortunately, this can lead to strongly undersampled segments on a ray since the three PDFS are
not perfect. Multiplying PDFs for product sampling can lead to still valid but far too small values in the
resulting PDF that would take several tens of thousand samples to converge out.
In order to combine the three PDFs, multiple-importance sampling is performed. Since we are dealing
with 1D PDFs on a ray and they are in the same domain, we weight them and add them up to arrive at a
single PDF that is then importance sampled.
REFERENCES
Jon Louis Bentley. 1975. Multidimensional Binary Search Trees Used for Associative Searching. Commun. ACM 18, 9 (Sept. 1975),
509–517.
H. W. Bertini. 1963. Monte Carlo Simulations on Intranuclear Cascades. Technical Report ORNL–3383. Oak Ridge National
Laboratory, Oak Ridge, TN, USA.
L. L. Carter, E. D. Cashwell, and W. M. Taylor. 1972. Monte Carlo Sampling with Continuously Varying Cross Sections Along
Flight Paths. Nuclear Science and Engineering 48, 4 (1972), 403–411.
Subrahmanyan Chandrasekhar. 1950. Radiative Transfer. Clarendon Press.
Andrew Clinton and Mark Elendt. 2009. Rendering Volumes with Microvoxels. In SIGGRAPH 2009: Talks (SIGGRAPH ’09). ACM,
New York, NY, USA, Article 47, 47:1–47:1 pages.
Michael F. Cohen, John Wallace, and Pat Hanrahan. 1993. Radiosity and Realistic Image Synthesis. Academic Press Professional,
Inc., San Diego, CA, USA.
Robert L. Cook, Thomas Porter, and Loren Carpenter. 1984. Distributed ray tracing. Computer Graphics (Proc. of SIGGRAPH) 18, 3
(Jan. 1984), 137–145.
S. N. Cramer. 1978. Application of the Fictitious Scattering Radiation Transport Model for Deep-Penetration Monte Carlo
Calculations. Nuclear Science and Engineering 65, 2 (1978), 237–253.
Roger Eckhardt. 1987. Stan Ulam, John von Neumann, and the Monte Carlo Method. Los Alamos Science, Special Issue (1987),
131–137.
Christian Eisenacher, Gregory Nichols, Andrew Selle, and Brent Burley. 2013. Sorted Deferred Shading for Production Path
Tracing. Computer Graphics Forum (2013).
Iliyan Georgiev, Jaroslav Křivánek, Stefan Popov, and Philipp Slusallek. 2012. Importance Caching for Complex Illumination.
Computer Graphics Forum 31, 2pt3 (2012), 701–710. EUROGRAPHICS ’12.
M. Hapala and V. Havran. 2011. Review: Kd-tree Traversal Algorithms for Ray Tracing. Computer Graphics Forum 30, 1 (March
2011), 199–213.
L. G. Henyey and J. L. Greenstein. 1941. Diffuse radiation in the Galaxy. Astrophysical Journal 93 (Jan. 1941), 70–83.
Frederik W Jansen. 1986. Data Structures for Ray Tracing. In Proceedings of a Workshop (Eurographics Seminars on Data Structures
for Raster Graphics. Springer-Verlag New York, Inc., 57–73.
James T. Kajiya. 1986. The Rendering Equation. Computer Graphics (Proc. of SIGGRAPH) (1986), 143–150.
Doyub Kim and Hyeong-Seok Ko. 2007. Eulerian Motion Blur. In Eurographics Workshop on Natural Phenomena, D. Ebert and
S. Merillou (Eds.). The Eurographics Association.
Christopher Kulla and Marcos Fajardo. 2012. Importance Sampling Techniques for Path Tracing in Participating Media. CGF
(Proc. of Eurographics Symposium on Rendering) 31, 4 (June 2012), 1519–1528.
Peter Kutz, Ralf Habel, Yining Karl Li, and Jan Novák. 2017. Spectral and Decomposition Tracking for Rendering Heterogeneous
Volumes. ACM Transactions on Graphics (Proceedings of SIGGRAPH 2017) 36, 4 (2017).
Tom Lokovic and Eric Veach. 2000. Deep Shadow Maps. In Proceedings of the 27th Annual Conference on Computer Graphics and
Interactive Techniques (SIGGRAPH ’00). ACM Press/Addison-Wesley Publishing Co., New York, NY, USA, 385–392.
David J. MacDonald and Kellogg S. Booth. 1990. Heuristics for Ray Tracing Using Space Subdivision. Vis. Comput. 6, 3 (May 1990),
153–166.
Stephen Marshall, Tim Speltz, Greg Gladstone, Krzysztof Rost, and Jon Reisch. 2017. Racing to the Finish Line: Effects Challenges
on Cars 3. In ACM SIGGRAPH 2017 Talks (SIGGRAPH ’17). ACM, New York, NY, USA.
Johannes Meng, Marios Papas, Ralf Habel, Carsten Dachsbacher, Steve Marschner, Markus Gross, and Wojciech Jarosz. 2015.
Multi-Scale Modeling and Rendering of Granular Materials. ACM Transactions on Graphics (Proceedings of SIGGRAPH) 34, 4
(July 2015).
Ken Museth. 2013. VDB: High-resolution Sparse Volumes with Dynamic Topology. ACM TOG 32, 3 (July 2013), 27:1–27:22.
Jan Novák, Andrew Selle, and Wojciech Jarosz. 2014. Residual Ratio Tracking for Estimating Attenuation in Participating Media.
ACM TOG (Proc. of SIGGRAPH Asia) 33, 6 (Nov. 2014), 179:1–179:11.
Ken H. Perlin and Eric M. Hoffert. 1989. Hypertexture. Computer Graphics (Proc. of SIGGRAPH) 23, 3 (July 1989), 253–262.
Matt Pharr and Greg Humphreys. 2010. Physically Based Rendering: From Theory to Implementation (2nd ed.). Morgan Kaufmann
Publishers Inc., San Francisco, CA, USA.
Matthias Raab, Daniel Seibert, and Alexander Keller. 2008. Unbiased Global Illumination with Participating Media. In Monte Carlo
and Quasi-Monte Carlo Methods 2006. Springer, 591–606.
Charles M. Schmidt and Brian C. Budge. 2002. Simple Nested Dielectrics in Ray Traced Images. Journal of Graphics Tools 7, 2
(2002), 1–8.
Production Volume Rendering • 97
H. R. Skullerud. 1968. The stochastic computer simulation of ion motion in a gas subjected to a constant electric field. Journal of
Physics D: Applied Physics 1, 11 (1968), 1567–1568.
Carlos Ureña, Marcos Fajardo, and Alan King. 2013. An Area-preserving Parametrization for Spherical Rectangles. In Proceedings
of the Eurographics Symposium on Rendering (EGSR ’13). Eurographics Association, 59–66.
Eric Veach. 1997. Robust Monte Carlo Methods for Light Transport Simulation. Ph.D. Dissertation. Stanford University, Stanford,
CA, USA.
Eric Veach and Leonidas J. Guibas. 1995. Optimally combining sampling techniques for Monte Carlo rendering (ACM SIGGRAPH
1995). 419–428.
Ryusuke Villemin and Christophe Hery. 2013. Practical Illumination from Flames. Journal of Computer Graphics Techniques
(JCGT) 2, 2 (31 December 2013), 142–155.
John von Neumann. 1951. Various Techniques Used in Connection with Random Digits. Journal of Research of the National Bureau
of Standards, Appl. Math. Series 12 (1951), 36–38.
Jiří Vorba, Ondřej Karlík, Martin Šik, Tobias Ritschel, and Jaroslav Křivánek. 2014. On-line Learning of Parametric Mixture Models
for Light Transport Simulation. ACM Transactions on Graphics (Proceedings of SIGGRAPH 2014) 33, 4 (Aug 2014).
Ingo Wald and Vlastimil Havran. 2006. On building fast kd-trees for ray tracing, and on doing that in O(N log N). In Proceedings
of IEEE Symposium on Interactive Ray Tracing 2006 (18-20). 61–69.
E.R. Woodcock, T. Murphy, P.J. Hemmings, and T.C. Longworth. 1965. Techniques used in the GEM code for Monte Carlo
neutronics calculations in reactors and other systems of complex geometry. In Applications of Computing Methods to Reactor
Problems. Argonne National Laboratory.
Magnus Wrenninge. 2009. Field3D. (2009). http://github.com/imageworks/Field3D
Magnus Wrenninge. 2012. Production Volume Rendering: Design and Implementation. CRC Press.
Magnus Wrenninge. 2015. Art-directable Multiple Volumetric Scattering. In ACM SIGGRAPH 2015 Talks (SIGGRAPH ’15). ACM,
New York, NY, USA, Article 24, 1 pages.
Magnus Wrenninge. 2016. Efficient Rendering of Volumetric Motion Blur Using Temporally Unstructured Volumes. Journal of
Computer Graphics Techniques (JCGT) 1 (31 January 2016), 1–34.
Magnus Wrenninge and Nafees Bin Zafar. 2011. Production Volume Rendering 1: Fundamentals (ACM SIGGRAPH 2011 Courses).
Magnus Wrenninge, Nafees Bin Zafar, Ollie Harding, Gavin Graham, Jerry Tessendorf, Victor Grant, Andrew Clinton, and Antoine
Bouthors. 2011. Production Volume Rendering 2: Systems (ACM SIGGRAPH 2011 Courses).
Magnus Wrenninge, Christopher D. Kulla, and Viktor Lundqvist. 2013. Oz: The Great and Volumetric.. In SIGGRAPH Talks. ACM,
46:1.
Magnus Wrenninge and Michael Rice. 2016. Volume Modeling Techniques in The Good Dinosaur. In ACM SIGGRAPH 2016 Talks
(SIGGRAPH ’16). ACM, New York, NY, USA, Article 63, 1 pages.
Yonghao Yue, Kei Iwasaki, Bing-Yu Chen, Yoshinori Dobashi, and Tomoyuki Nishita. 2011. Toward Optimal Space Partitioning for
Unbiased, Adaptive Free Path Sampling of Inhomogeneous Participating Media. CGF (Proc. of Pacific Graphics) 30, 7 (2011),
1911–1919.
Yonghao Yue, Kei Iwasaki, Bing-Yu Chen, Yoshinori Dobashi, and Tomoyuki Nishita. 2010. Unbiased, Adaptive Stochastic Sampling
for Rendering Inhomogeneous Participating Media. ACM TOG (Proc. of SIGGRAPH Asia) 29, 6 (Dec. 2010), 177:1–177:8.
C. D. Zerby, R. B. Curtis, and H. W. Bertini. 1961. The Relativistic Doppler Problem. Technical Report ORNL-61-7-20. Oak Ridge
National Laboratory, Oak Ridge, TN, USA.