In their presentation at SIGGRAPH 2015 Electronic Arts presented method of volumetric rendering using 3D texture aligned with view frustum.

This technique needs two steps:

  • Injection of color and density into 3D texture,
  • Integration along Z axis of texture.

Integration code example is on slide 27. However, it is stated as being wrong. Do anyone can explain what is wrong with that (pretty standard raymarching integration) code?


What is wrong with it seems to be explained on the next two slides: it leads to non-energy-conserving results, where the apparent brightness of the volume changes depending on the scattering coefficient.

My read of it is that the "wrong" integration code implicitly assumes a constant transmittance over the extent of each voxel. But the trouble is, when the scattering coefficient is high, the transmittance will fall off significantly within a single voxel. For instance, if you have voxels of size 10 cm, but the scattering coefficient is 1 / (5 cm), then the transmittance falls off by exp(10 cm / 5 cm), or about a factor of 7.4 over the length of the voxel!

Therefore, according to slide 28, a better approach is to explicitly account for the transmittance falloff over the voxel length, while still assuming constant inscattered light. Fortunately the integral has a simple closed-form solution. So, they're saying to evaluate that formula per voxel in the integration loop, in place of the former "wrong" one.

For completeness: in the code from slide 27, replace this line:

accumScatteringTransmittance.rgb += scatteringExtinction.rgb *

with this:

accumScatteringTransmittance.rgb += scatteringExtinction.rgb *
    accumScatteringTransmittance.a *
    ((1.0 - transmittance) / scatteringExtinction.a);

Here, accumScatteringTransmittance.a is the transmittance at the point the ray enters the voxel (i.e. the resultant transmittance of all the voxels in front of it), and then the ((1.0 - transmittance) / scatteringExtinction.a) factor accounts for the varying transmittance within the voxel.

  • $\begingroup$ Thanks. I suspected such thing because I recently experimented with cloud raymarchind sample code form here: gamedev.net/forums/topic/680832-horizonzero-dawn-cloud-system/… It probably has corrected approach. I don't exacly understand how to implement this formula though. It looks like when putting S before the formula, what was left in between parenthesis is transmittance? I need to put it in output.w for further reconstruction. $\endgroup$
    – narthex
    Oct 22 '17 at 9:12
  • $\begingroup$ @narthex I added to the answer with my guess as to what the code should look like with the modified integration. $\endgroup$ Oct 22 '17 at 22:11
  • $\begingroup$ This is my comparison - standard vs corrected (above code): imgur.com/a/POTaD. But differences only get visible with very high scattering. Also correction leads to division by zero so small epsilon is needed. $\endgroup$
    – narthex
    Oct 27 '17 at 14:02

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.