<p>This question is a bit too broad to answer, but I'll try.</p>

<p>Right now you have a screenshot and you are not really sure whether it's correct or not, and if it turns out it is not, it will be difficult to know what is incorrect about it. I would recommend to split your problem into smaller, isolated, problems that can be validated separately.</p>

<p>For example, is the lighting information correct at each point? Are the coordinates (screen space vs world space) correct? To answer these questions you could maybe represent the distance from the light at each point, with something like the following, and check that the visual result is consistent with your scene.</p>

<pre><code>color = fract(length(light.position - currentPosition));
</code></pre>

<p>Similarly, is the shadowing correct? This problem is unrelated to scattering so you can check that it  is correct by just having a constant light contribution (your commented code seems to indicate that you have tried so already). You will see quickly if a volumetric shadow is properly cast from occluding geometry.</p>

<pre><code>if (!shadow)
{
    accumFog += light.diffuse;
}
</code></pre>

<p>Finally you can test the scattering without any shadow, and make sure it behaves as expected. For example, you should get the same fog color when changing the number of steps. Moreover, the scattering contribution should be less noticeable when there is geometry close to the camera (make sure you stop marching when you reach the scene depth).</p>

<p>Once you are confident the separate parts are working, you can combine them until you reach the final result. I have suggested a few points to check, but you might check other points as well, as you see fit.</p>

<blockquote>
  <p>At the end should I just blend the volumetric light buffer with the deferred shading final buffer?</p>
</blockquote>

<p>Since the lighting is additive, you just need to do an additive blend of the resulting buffer on your scene. However if you later decide to also handle distance fog (contrast fading in the distance), then a different blending will be necessary.</p>

<p>P.S.: I happen to have written <a href="http://www.ctrl-alt-test.fr/2018/a-dive-into-the-making-of-immersion/" rel="nofollow noreferrer">about volumetric lighting in this article</a> (see part "Volumetric lighting"). It doesn't go into details, but maybe it will be helpful nonetheless.</p>

CC BY-SA 4.0
2018-10-29T08:24:50.503Z
2018-10-29T08:24:50.503Z
Julien Guertault
<p>I'm implementing basic volumetric lighting using deferred shading (gbuffer + render to screen quad) and basic shadow mapping. So,  I am sending the position texture and shadow map to a separate shader, applying ray-marching for every position and computing the scattering accumulation when is not in shadow. The question is , how do I know I am getting the right results? is it just by rendering the volumetric lighting texture to quad and look for colored patches in the scene? these are my results:</p>

<p>Original Scene
<a href="https://i.sstatic.net/2FrTy.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/2FrTy.png" alt="enter image description here"></a></p>

<p>Volumetric Light buffer
<a href="https://i.sstatic.net/M1pmp.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/M1pmp.png" alt="enter image description here"></a></p>

<p>This is the code of my volumetric fragment shader:</p>

<pre><code>uniform sampler2D positionMap; 
uniform sampler2D shadowMap;
float NB_STEPS = 3.0f;
int NB_STEPS_INT = 3;
float G_SCATTERING = 0.7f;
out vec4 fragColor;

void main()
{ 

vec2 texCoord = vec2(gl_FragCoord.x/width,gl_FragCoord.y/height);
vec3 worldPosition = texture2D(positionMap,texCoord).xyz;
vec3 startPosition = ViewPos;

vec3 rayVector = worldPosition.xyz- startPosition;
float rayLength = length(rayVector);
vec3 rayDirection = normalize(rayVector);
float stepLength = rayLength / NB_STEPS;
vec3 step = rayDirection * stepLength;

vec3 currentPosition = startPosition;

vec3 accumFog = vec3(0.0f);
for(int i = 0;  i &lt; NB_STEPS_INT; i++)
{
  bool shadow = ShadowCalculation(currentPosition);
  if(!shadow)
  {
    accumFog += ComputeScattering(dot(rayDirection, light.position)) * light.diffuse;
    //accumFog +=  light.diffuse;
  }
  currentPosition += step;
}

accumFog /= NB_STEPS;

fragColor = vec4(accumFog, 1);

}
</code></pre>

<p>I am computing the scattering factor like this:</p>

<pre><code>float ComputeScattering(float lightDotView)
{
  float result = 1.0f - G_SCATTERING * G_SCATTERING;
  result /=  (4.0f * PI * pow(1.0f + G_SCATTERING * G_SCATTERING - (2.0f * G_SCATTERING) *    lightDotView, 1.5f));
  return result;
}
</code></pre>

<p>At the end should I just blend the volumetric light buffer with the deferred shading final buffer?</p>

<p>I appreciate the help.</p>

<glsl><deferred-rendering><volumetric-scattering>
GLSL Debugging Volumetric light
Camilo
# GLSL Debugging Volumetric light

(Asked by: username_0 on 2018-10-27)

I'm implementing basic volumetric lighting using deferred shading (gbuffer + render to screen quad) and basic shadow mapping. So, I am sending the position texture and shadow map to a separate shader, applying ray-marching for every position and computing the scattering accumulation when is not in shadow. The question is , how do I know I am getting the right results? is it just by rendering the volumetric lighting texture to quad and look for colored patches in the scene? these are my results:

Original Scene
[![enter image description here](https://i.sstatic.net/2FrTy.png)](https://i.sstatic.net/2FrTy.png)

Volumetric Light buffer
[![enter image description here](https://i.sstatic.net/M1pmp.png)](https://i.sstatic.net/M1pmp.png)

This is the code of my volumetric fragment shader:

```
uniform sampler2D positionMap; 
uniform sampler2D shadowMap;
float NB_STEPS = 3.0f;
int NB_STEPS_INT = 3;
float G_SCATTERING = 0.7f;
out vec4 fragColor;

void main()
{ 

vec2 texCoord = vec2(gl_FragCoord.x/width,gl_FragCoord.y/height);
vec3 worldPosition = texture2D(positionMap,texCoord).xyz;
vec3 startPosition = ViewPos;

vec3 rayVector = worldPosition.xyz- startPosition;
float rayLength = length(rayVector);
vec3 rayDirection = normalize(rayVector);
float stepLength = rayLength / NB_STEPS;
vec3 step = rayDirection * stepLength;

vec3 currentPosition = startPosition;

vec3 accumFog = vec3(0.0f);
for(int i = 0;  i < NB_STEPS_INT; i++)
{
  bool shadow = ShadowCalculation(currentPosition);
  if(!shadow)
  {
    accumFog += ComputeScattering(dot(rayDirection, light.position)) * light.diffuse;
    //accumFog +=  light.diffuse;
  }
  currentPosition += step;
}

accumFog /= NB_STEPS;

fragColor = vec4(accumFog, 1);

}

```

I am computing the scattering factor like this:

```
float ComputeScattering(float lightDotView)
{
  float result = 1.0f - G_SCATTERING * G_SCATTERING;
  result /=  (4.0f * PI * pow(1.0f + G_SCATTERING * G_SCATTERING - (2.0f * G_SCATTERING) *    lightDotView, 1.5f));
  return result;
}

```

At the end should I just blend the volumetric light buffer with the deferred shading final buffer?

I appreciate the help.

**Tags:** glsl, deferred-rendering, volumetric-scattering


---

## 1 answers

### Answer by username_1 on 2018-10-29. Score: 1

This question is a bit too broad to answer, but I'll try.

Right now you have a screenshot and you are not really sure whether it's correct or not, and if it turns out it is not, it will be difficult to know what is incorrect about it. I would recommend to split your problem into smaller, isolated, problems that can be validated separately.

For example, is the lighting information correct at each point? Are the coordinates (screen space vs world space) correct? To answer these questions you could maybe represent the distance from the light at each point, with something like the following, and check that the visual result is consistent with your scene.

```
color = fract(length(light.position - currentPosition));

```

Similarly, is the shadowing correct? This problem is unrelated to scattering so you can check that it is correct by just having a constant light contribution (your commented code seems to indicate that you have tried so already). You will see quickly if a volumetric shadow is properly cast from occluding geometry.

```
if (!shadow)
{
    accumFog += light.diffuse;
}

```

Finally you can test the scattering without any shadow, and make sure it behaves as expected. For example, you should get the same fog color when changing the number of steps. Moreover, the scattering contribution should be less noticeable when there is geometry close to the camera (make sure you stop marching when you reach the scene depth).

Once you are confident the separate parts are working, you can combine them until you reach the final result. I have suggested a few points to check, but you might check other points as well, as you see fit.

> At the end should I just blend the volumetric light buffer with the deferred shading final buffer?

Since the lighting is additive, you just need to do an additive blend of the resulting buffer on your scene. However if you later decide to also handle distance fog (contrast fading in the distance), then a different blending will be necessary.

P.S.: I happen to have written [about volumetric lighting in this article](http://www.ctrl-alt-test.fr/2018/a-dive-into-the-making-of-immersion/) (see part "Volumetric lighting"). It doesn't go into details, but maybe it will be helpful nonetheless.


---

