<p>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.</p>

<p>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!</p>

<p>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 <em>that</em> formula per voxel in the integration loop, in place of the former "wrong" one.</p>

<p>For completeness: in the code from slide 27, replace this line:</p>

<pre><code>accumScatteringTransmittance.rgb += scatteringExtinction.rgb *
    accumScatteringTransmittance.a;
</code></pre>

<p>with this:</p>

<pre><code>accumScatteringTransmittance.rgb += scatteringExtinction.rgb *
    accumScatteringTransmittance.a *
    ((1.0 - transmittance) / scatteringExtinction.a);
</code></pre>

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

CC BY-SA 3.0
2017-10-22T09:12:09.553Z
Thanks. I suspected such thing because I recently experimented with cloud raymarchind sample code form here: https://www.gamedev.net/forums/topic/680832-horizonzero-dawn-cloud-system/?page=3&tab=comments#comment-5319203 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.
mdkdy
CC BY-SA 3.0
2017-10-22T22:11:14.583Z
@narthex I added to the answer with my guess as to what the code should look like with the modified integration.
Nathan Reed
CC BY-SA 3.0
2017-10-27T14:02:14.517Z
This is my comparison - standard vs corrected (above code): https://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.
mdkdy
CC BY-SA 3.0
2017-10-21T16:19:08.130Z
2017-10-22T22:10:35.020Z
2017-10-22T22:10:35.020Z
Nathan Reed
<p>In their <a href="https://www.slideshare.net/DICEStudio/physically-based-and-unified-volumetric-rendering-in-frostbite" rel="noreferrer">presentation</a> at SIGGRAPH 2015 Electronic Arts presented method of volumetric rendering using 3D texture aligned with view frustum.</p>

<p>This technique needs two steps:</p>

<ul>
<li>Injection of color and density into 3D texture,</li>
<li>Integration along Z axis of texture.</li>
</ul>

<p>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?</p>

<raymarching><3dtexture><volumetric-scattering>
Volumetric integration in Frostbite
mdkdy
# Volumetric integration in Frostbite

(Asked by: username_0 on 2017-10-21)

In their [presentation](https://www.slideshare.net/DICEStudio/physically-based-and-unified-volumetric-rendering-in-frostbite) 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?

**Tags:** raymarching, 3dtexture, volumetric-scattering


---

## 1 answers

### Answer by username_1 on 2017-10-21. Score: 6 | Accepted answer

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 *
    accumScatteringTransmittance.a;

```

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.

> **Comments:**
> **username_0**: Thanks. I suspected such thing because I recently experimented with cloud raymarchind sample code form here: https://www.gamedev.net/forums/topic/680832-horizonzero-dawn-cloud-system/?page=3&tab=comments#comment-5319203 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.  
> **username_1**: @narthex I added to the answer with my guess as to what the code should look like with the modified integration.  
> **username_0**: This is my comparison - standard vs corrected (above code): https://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.  

---

