Scale Depth Value Sampled

Started by
7 comments, last by Andr 3 years, 1 month ago

Hello!

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!

Advertisement

Andr said:
Due to this scaling (and the inverse multiplication) i am getting some shimmering in the horizon

Are you sure what you see is not banding due to depth buffer precision? (banding remains constant if scene and camera is static, ‘shimmering’ would mean the artifacts look different each frame even then.)

I assume changing math regarding scaling would have no effect on this issue. The usual way to fix banding is turning it into noise by adding some randomness. Noise is much more acceptable, and if you have TAA it should smooth out the noise. (Just make sure your random value is different for each pixel and frame.)

But the other thing you might want to try first is using another projection method to reduce precision issues in the first place, like ‘Reversed Z’, which most people seem to use nowadays.

@JoeJ Hi Joe!

I think its shimmering because it's only noticeable when the camera is moving and not when is static. I am definitely getting some banding when going up in the atmosphere but i am not sure they are related.

I think the math might have an influence because when in other parts of the project when i used the original inverted MVP matrix and then scale it by 1/1000 i would get the a shimmering effect. This went a way when i used a scaled down inverted MVP matrix for the world position calculations.

Yeah, i will definitely implement reverse z buffer but i wanted to make sure i wasn't masking any issues in the code before.

I have uploaded a video of the issue here, look closely behind the rock and at the horizon line when the camera is moving up and down. Its more noticeable when rendering in native resolution:

Yeah, can see something like z fighting where the ocean clips the land, but atmosphere details disappear in video compression artifacts i guess.
If there is some raycasting involved, this could be more a reason than the depth precision maybe. Artifact may be pronounced at the distance eventually because accumulating more marching results. Some noise / dither stuff to offset ray start position would fix it, while reversed z would't, if that's the true reason. (tracing intervals and volume grid can cause some kind of moire artifact)

@JoeJ Thank you for your answers!

Yeah, i thought so, i have uploaded a new video with the DepthBufferWorldPos outputed to the screen, there's definitely something funky going on on the far plane. Yeah, there is raymarching involved that might contribute to the issue as well.

FYI this is the algorithm used:

I'm not familiar with the algorithm, bur I'm curious if the shimmering on the shore disappears if you set a very distant near plane (close to your far plane). I think that would make the depth range have more precision at the distant shore regions.

My tutorials on youtube: https://www.youtube.com/channel/UC9CQOdT1A9JlAks0-PF5vvw
Latest Tutorials:
A simple and intuitive ray triangle intersection algorithm https://youtu.be/XgUhgSlQvic

Möller Trumbore ray triangle intersection explained visually https://youtu.be/fK1RPmF_zjQ

Setting up OpenAL c++ visual studio https://youtu.be/WvND0djMcfE

@mattstone2728 Hi!

I have actually set it to near plane 2000 and far plane 2500 and i still get that shimmering. Its definitely related to the position conversion as per the video above :/

@mattstone2728 @joej So i actually managed to solve it. It was related to the precision, but indirectly. When getting to close to the zero Y value, and as the algorithm is in KM, the distances start to get very small and thus getting into precision errors. The solution was to limit the position of the camera so the algorithm think that is at a safe distance from zero (say ~0.1 km).

Thanks everyone for your input!

This topic is closed to new replies.

Advertisement