How are volumetric effects such as smoke, fog, or clouds rendered by a raytracer? Unlike solid objects, these don't have a well-defined surface to compute an intersection with.



The appearance of volumes (also called participating media) in nature is caused by tiny particles, such as dust, water droplets or plankton, that are suspended in the surrounding fluid, such as air or water. These particles are solid objects, and light refracts or reflects off of these objects as it would on a normal surface. In theory, participating media could therefore be handled by a traditional ray tracer with only surface intersections.

Statistical Model

Of course, the sheer number of these particles makes it infeasible to actually raytrace them individually. Instead, they are approximated with a statistical model: Because the particles are very small, and the distance between the particles is much larger than the particle size, individual interactions of light with the particles can be modeled as statistically independent. Therefore, it is a reasonable approximation to replace the individual particles with continuous quantities that describe the "average" light-particle interaction at that certain region in space.

For physically based volumetric light transport, we replace the inconceivably many particles with a continuous participating medium that has two properties: The absorption coefficient, and the scattering coefficient. These coefficients are very convenient for ray tracing, as they allow us to compute the probability of a ray interacting with the medium - that is, the probability of striking one of the particles - as a function of distance.

The absorption coefficient is denoted $\sigma_a$. Say a ray of light wants to travel $t$ meters inside the participating medium; the probability of making it through unabsorbed -- i.e. not hitting one of the particles and being absorbed by it -- is $e^{-t\cdot\sigma_a}$`. As t increases, we can see that this probability goes to zero, that is, the longer we travel through the medium, the more likely it is to hit something and be absorbed. Very similar things hold for the scattering coefficient $\sigma_s$: The probability of the ray not hitting a particle and being scattered is $e^{-t\cdot\sigma_s}$; that is, the longer we travel through a medium, the more likely it is that we hit a particle and are scattered into a different direction.

Usually, these two quantities are folded into a single extinction coefficient, $\sigma_t = \sigma_a + \sigma_s$. The probability of traveling $t$ meters through a medium without interacting with it (neither being absorbed or scattered) is then $e^{-t\cdot\sigma_t}$. On the other hand, the probability of interacting with a medium after $t$ meters is $1 - e^{-t\cdot\sigma_t}$.

Rendering with Participating Media

The way this is used in physically based renderers is as follows: When a ray enters a medium, we probabilistically stop it inside the medium and have it interact with a particle. Importance sampling the interaction probability$1 - e^{-t\cdot\sigma_t}$ yields a distance $t$; this tells us that the ray traveled $t$ meters in the medium before striking a particle, and now one of two things happens: Either the ray gets absorbed by the particle (with probability $\frac{\sigma_a}{\sigma_t}$), or it gets scattered (with probability $\frac{\sigma_s}{\sigma_t}$).

How the ray is scattered is described by the phase function and depends on the nature of the particles; the Rayleigh phase function describes scattering from spherical particles smaller than the wavelength of light (e.g. our atmosphere); the Mie phase function describes scattering from spherical particles of similar size than the wavelength (e.g. water droplets); in graphics, usually the Henyey-Greenstein phase function is used, originally applied to scattering from interstellar dust.

Now, in graphics, we don't normally render pictures of an infinite medium, but render media inside a scene consisting of hard surfaces as well. In that case, we first fully trace the ray until it hits the next surface, completely ignoring the participating medium; this gives us the distance to the next surface, $t_{Max}$. We then sample an interaction distance $t$ in the medium as described before. If $t \lt t_{Max}$, the ray hit a particle on the way to the next surface and we either absorb it or scatter it. If $t \geq t_{Max}$, the ray made it through unscathed and interacts with the surface as usual.


This post was only a small introduction to rendering with participating media; among other things, I completely ignored spatially varying coefficients (which you need for clouds, smoke, etc.). Steve Marschner's notes are a good resource, if you're interested. In general, participating media are very difficult to render efficiently, and you can go a lot more sophisticated than what I described here; there's Volumetric Photon Mapping, Photon Beams, Diffusion approximations, Joint Importance Sampling and more. There's also interesting work on granular media that describes what to do when the statistical model breaks down, i.e. particle interactions are no longer statistically independent.


One way to do it - which isn't exactly the "go to" solution, but can work nicely, is to find the distance that the ray traveled through the volume and use integration of some density function to calculate how much "stuff" was hit.

Here is a link with an example implementation: http://blog.demofox.org/2014/06/22/analytic-fog-density/


Depends on the volume efffect.

Uniform volume effects that do not belong do scattering can be simulated by just calculating ray enter and ray exit distances.

Otherwise you need to do integration of the ray path, also known as ray marching. To avoid needing to shoot secondary rays the raymarching is often coupled with some sort of cache, like depthmap, deepmaps, brick maps or voxel clouds for light shadowing, etc. This way you dont necceserily need to march the whole scene. Similar caching is often done to the volume procedural texture.

It is also possible to convert the texture to surface primitives like boxes, spheres or planes that have some suitable soft edged texture. You can then use normal rendering techniques to solve the volumetric effect. The problem with this is that you usually need lots of primitives. Additionally the shape of the primitive may show up as too uniform sampling.

  • $\begingroup$ Just want to note that you can do actual integration of a ray path analytically as well, you don't have to use Ray marching if it's undesirable. $\endgroup$ – Alan Wolfe Aug 13 '15 at 15:29
  • $\begingroup$ @AlanWolfe thats what you do in the uniform case, however if the medium participates with geometry then you need to do something more nifty. Anyway i didnt claim this is all methods. $\endgroup$ – joojaa Aug 13 '15 at 15:53
  • $\begingroup$ For sure, just adding to your answer. When you say uniform case not sure what you mean exactly but for the case of fog, it doesn't have to be uniform density, just some density function that you can integrate. Is that what you meant by uniform case? $\endgroup$ – Alan Wolfe Aug 13 '15 at 16:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.