I am working on a project where I supply depth values to the depth buffer from depth values stored in a png file rendered out from Maya. It’s the effect they used a lot in the old days so they could get dynamic objects to cull with a pre-rendered 3D scene.
Anyway, I can render an orthographic scene and the depth values work as expected, but as soon as I try it with a perspective camera it’s a no go. It acts like the depth is way towards the front of the camera, but I’ve tried scaling and offsetting values and nothing works as predicted.
Is there something that I don’t understand regarding depth values? Aren’t they just values that range from 0 to 1? I’ve looked all over for answers and nothing seems to touch on this subject specifically.
The following shader is called by Graphics.Blit in my post effect that transfers the depth of my png into the depth buffer. Does anything look out of place? Do I need to adjust the values before transferring the depth from the image and into the buffer?
Here’s a picture that represents a debug scene I created showing the issue. White represents the far plan, and grey (0.5, 0.5, 0.5) should be exactly in between the near and far planes. It works for orthographic cameras, but not for perspective.
the depth values are indeed in range [0,1], but the difference between orthographic and perspective projection is that in perspective depth is non-linear. There’s a lot of docs online about how exactly it’s calculated.
From what I just read it sounds like non-linear depth is the distance from the camera/eye origin to the fragment, and linear is distance to the camera/eye plane. I thought it just stored depth one way. I will play around with some things and come back if I have any more questions.
My hat goes off to the math guys who came up with all this stuff. I thought I had a pretty good understanding of the graphics pipeline, that is until I hit the depth buffer challenge .
The depth buffer is still a little bit of a mystery to me, but, I did stumble upon a solution. My idea was to convert the linear depth value to view space, multiply it with the projection matrix, then store it into SV_Depth. Here was the conversion (which for those excited for a solution, this isn’t it):
float4 vertex = i.vertex; // initially assign entire incoming vertex pos
// assign my pre rendered z position (I was just guessing with the w at this point)
vertex.z = preRenderedZ * vertex.w;
vertex = mul(UNITY_MATRIX_P, vertex)
o.depth = vertex.z;
So yeah, that didn’t work
Then all this got me wondering about what w was for in the first place, so I went on a quest to learn more about it. I found this site which explains it pretty well.
However, that still didn’t help me find what I was looking for, so I did a search for “unity pre rendered depth”. Duh right? Well, I did searches similar to that before but the sites were always about enabling depth in a render texture, which isn’t what I wanted. This time I found this post (it’s the answer at the bottom that is of interest): https://gamedev.stackexchange.com/questions/97034/3d-game-with-pre-rendered-background
At the bottom they guy points everyone to this place, which was in fact what I was looking for:
It took a while to figure this one out, but well worth it, because now I know what w is used for and I know about linear and non-linear depth buffers.
I noticed that there is a depth sacle and a offset in your code. Why there is such a thing? I find that my orthographic view need a scale and offset to work, but I don’t know why.