# Scale Sampled Depth Value

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:

https://www.youtube.com/watch?v=kEaU72NWq8I

## 1 Answer

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$$.

• 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. Apr 12 at 13:01