I am currently porting the atmosphere algorithm used by the UE4 engine to my engine.

As the original algorithm from Bruneton is in Kilometers i had to adapt it to my engine which uses meters. Everything is working and its correctly scaled now but i am having some z precision issues on the horizon when drawing the fog. This, i believe, i due to the following math:

float DepthBufferValue = texture(ViewDepthTexture, depthValueUV).r;
vec3 depthClipSpace = vec3(pixPos / vec2(gResolution) * vec2(2.0f) - vec2(1.0f), DepthBufferValue);
vec4 DepthBufferWorldPos = gInvViewProjMat * vec4(depthClipSpace, 1.0);
DepthBufferWorldPos /= DepthBufferWorldPos.w; // perspective division
DepthBufferWorldPos.xyz *= 0.001; 

Here, i am basically reading the depth texture, getting the real world position value and scaling it to be in KMs. Due to this scaling (and the inverse multiplication) i am getting some shimmering in the horizon (where the z distance is the greatest)

Since the depth equation is equal to:

 d = a * (1/z) + b 

(with a = near, b = far clip and z the distance from camera) is there any mathematical way to scale the DepthBufferValue to a value where the world position would be in kilometers?

In a more practical way, imagining that we have a World Position of (0, 1000, 0) and that gives us a DepthBufferValue of 0.998, can we scale that 0.998 value to the value that we would obtain if we had used the World Position (0, 1, 0) ? (Assuming of course the same near and far clips)

Many thanks!

Edit: This is the DepthBufferWorldPos outputed to the screen:



1 Answer 1


Algebraically speaking, it's not too hard to modify $d$ in order to scale $z$. If you want to scale $z$ by a factor of $c$, giving $z' = cz$, then $$ \begin{aligned} d' &= a \frac{1}{z'} + b \\ &= a \frac{1}{cz} + b \\ (d' - b)c &= a \frac{1}{z} \\ &= d - b \\ d' &= \frac{d - b}{c} + b \end{aligned} $$ In short, to scale $z$ by a factor of $c$, you would take the depth value and subtract $b$, scale by $1/c$, then add $b$ back again.

Note that if you use a projection with reversed Z and an infinite far plane, then $b = 0$, which simplifies this to just $d' = d/c$.

  • $\begingroup$ Yeah, that seems to work. Unfortunately it did not solve the shimmering issue, but it seems that the shimmering related to the world position is now fixed and i have another problem elsewhere. I have added a video to the original post with the world position before i added your scaling. $\endgroup$ Commented Apr 12, 2021 at 13:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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