Naruto-kun 442 Report post Posted August 28, 2016 (edited) Hi guysI have the depth buffer for a scene, along with the far and near clip plane values (I also have the units of measurement), the vertical FOV, and the aspect ratio of the projection. The scene is using a standard D3DXMatrixPerspectiveFovLH projection matrix. The depth buffer values are normalised (+-1.0f).How would I work backwards so I can get the distance to the pixel in the scene? I tried making an inverse matrix of the projection matrix and multiplying the screen and depth coordinates of the pixel from it but I didn't get the expected results. Edited August 28, 2016 by Naruto-kun 0 Share this post Link to post Share on other sites
alvaro 21272 Report post Posted August 28, 2016 You should be able to figure this one out yourself. You can either read the documentation carefully to see what the values mean, or you can reverse engineer it: Set up a few test situations where you know how far the pixel is and look at what values you get for those cases. You can probably figure out a formula easily from a few examples. 0 Share this post Link to post Share on other sites
Hodgman 51433 Report post Posted August 28, 2016 I tried making an inverse matrix of the projection matrix and multiplying the screen and depth coordinates of the pixel from it but I didn't get the expected results.Make sure the coordinates are in NDC: -1 to 1 for x/y (and z in GL) and 0 to 1 for z in D3D. Then after the matrix multiply, divide xyz by w to get a views pace position, and calculate its length to get distance from the camera. 0 Share this post Link to post Share on other sites
Naruto-kun 442 Report post Posted August 28, 2016 (edited) You should be able to figure this one out yourself. You can either read the documentation carefully to see what the values mean, or you can reverse engineer it: Set up a few test situations where you know how far the pixel is and look at what values you get for those cases. You can probably figure out a formula easily from a few examples. Unfortunately this one isn't quite possible because the program I am working with has no way to provide me with the distance to a pixel so I would be working blind (I am working through an API, not source of the program). I only have a rough guess that I can work with which is anything but reliable. I tried making an inverse matrix of the projection matrix and multiplying the screen and depth coordinates of the pixel from it but I didn't get the expected results.Make sure the coordinates are in NDC: -1 to 1 for x/y (and z in GL) and 0 to 1 for z in D3D.Then after the matrix multiply, divide xyz by w to get a views pace position, and calculate its length to get distance from the camera.I did a shader debug run using VS 2013's shader debugging library. The screen coordinates I calculate using texture coordinates from the area of the screen I am sampling (I convert them to the proper +-1.0f ranges), and I can confirm the Z values are 0 to 1. After multiplying with the inverse projection matrix I divide the xyz by the w and put it through the length function. The value still comes out quite low (like around 1.2 to 1.8) and my final image looks a bit like a hyperbola.I will post some screenshots shortly of the program which may help you visualise things a bit more effectively. Edited August 28, 2016 by Naruto-kun 0 Share this post Link to post Share on other sites
Naruto-kun 442 Report post Posted August 28, 2016 Here is the geometry shader I am working with. The basic idea, is that the X axis of the texture (depth buffer) I am sampling from will correlate with the X axis of the final image, and the distance to the pixel calculated using the depth buffer will correspond to the Y axis of the final image (in otherwords, a modified B-scope radar display where the horizontal corresponds to the azimuth of the return and the vertical corrosponds to the slant range).[maxvertexcount(80)] void GS( point GS_INPUT sprite[1], inout TriangleStream<PS_INPUT> triStream ) { PS_INPUT v; uint ux = sprite[0].id % 256; uint uy = sprite[0].id / 256; float x = float(ux) / 256.0f; float y = float(uy) / 75.0f; float x1 = x + (1.0f / 256.0f); float y1 = y + (1.0f / 75.0f); float4 fdepth = float4( depth.SampleLevel(SampleType, float2(x, y1), 0), depth.SampleLevel(SampleType, float2(x, y), 0), depth.SampleLevel(SampleType, float2(x1, y1), 0), depth.SampleLevel(SampleType, float2(x1, y), 0) ); float4 v1 = float4((2.0f*x) - 1.0f, 1.0f - (2.0f*y1), fdepth.x, 1.0f); float4 v2 = float4((2.0f*x) - 1.0f, 1.0f - (2.0f*y), fdepth.y, 1.0f); float4 v3 = float4((2.0f*x1) - 1.0f, 1.0f - (2.0f*y1), fdepth.z, 1.0f); float4 v4 = float4((2.0f*x1) - 1.0f, 1.0f - (2.0f*y), fdepth.w, 1.0f); float4 m1 = mul(v1, inprj); float4 m2 = mul(v2, inprj); float4 m3 = mul(v3, inprj); float4 m4 = mul(v4, inprj); float l1 = length(m1.xyz / m1.w); float l2 = length(m2.xyz / m2.w); float l3 = length(m3.xyz / m3.w); float l4 = length(m4.xyz / m4.w); v.m = 0; v.p.x = v1.x; v.p.y = l1 - 1.0f; v.p.zw = float2(0, 1.0f); v.t = float2(x, y1); triStream.Append(v); v.p.x = v2.x; v.p.y = l2 - 1.0f; v.p.zw = float2(0, 1.0f); v.t = float2(x, y); triStream.Append(v); v.p.x = v3.x; v.p.y = l3 - 1.0f; v.p.zw = float2(0, 1.0f); v.t = float2(x1, y1); triStream.Append(v); v.p.x = v4.x; v.p.y = l4 - 1.0f; v.p.zw = float2(0, 1.0f); v.t = float2(x1, y); triStream.Append(v); triStream.RestartStrip(); } Here is the first sample, using the top left corner of the texture source image (dimensions are 256x75). The screenshot below gives you an idea of where the camera is looking. The actual texture source image would only contain a thin strip from the center of the screenshot.ux 0 uint uy 0 uint x 0.000000000 float y 0.000000000 float x1 0.003900000 float y1 0.013300000 float fdepth x = 0.968700000, y = 0.964700000, z = 0.968600000, w = 0.964700000 float4 m1 x = -1.048700000, y = 0.063800000, z = -0.099900000, w = 1.068700000 float4 m2 x = -1.048700000, y = 0.065500000, z = -0.099900000, w = 1.064700000 float4 m3 x = -1.040500000, y = 0.063800000, z = -0.099900000, w = 1.068600000 float4 m4 x = -1.040500000, y = 0.065500000, z = -0.099900000, w = 1.064700000 float4 l1 0.987600000 float l2 0.991300000 float l3 0.980000000 float l4 0.983700000 float //Inverse projection matrix inprj[0] x = 1.048700000, y = 0.000000000, z = 0.000000000, w = 0.000000000 float4 inprj[1] x = 0.000000000, y = 0.065500000, z = 0.000000000, w = 0.000000000 float4 inprj[2] x = 0.000000000, y = 0.000000000, z = 0.000000000, w = 1.000000000 float4 inprj[3] x = 0.000000000, y = 0.000000000, z = -0.099900000, w = 0.100000000 float4 Here is what the final output looks like. A bit confusing to say the least.Here I have the camera even further from the target.ux 0 uint uy 0 uint x 0.000000000 float y 0.000000000 float x1 0.003900000 float y1 0.013300000 float fdepth x = 0.999300000, y = 0.999200000, z = 0.999300000, w = 0.999200000 float4 m1 x = -1.048700000, y = 0.063800000, z = -0.099900000, w = 1.099300000 float4 m2 x = -1.048700000, y = 0.065500000, z = -0.099900000, w = 1.099200000 float4 m3 x = -1.040500000, y = 0.063800000, z = -0.099900000, w = 1.099300000 float4 m4 x = -1.040500000, y = 0.065500000, z = -0.099900000, w = 1.099200000 float4 l1 0.960000000 float l2 0.960300000 float l3 0.952600000 float l4 0.952900000 float //Inverse projection matrix inprj[0] x = 1.048700000, y = 0.000000000, z = 0.000000000, w = 0.000000000 float4 inprj[1] x = 0.000000000, y = 0.065500000, z = 0.000000000, w = 0.000000000 float4 inprj[2] x = 0.000000000, y = 0.000000000, z = 0.000000000, w = 1.000000000 float4 inprj[3] x = 0.000000000, y = 0.000000000, z = -0.099900000, w = 0.100000000 float4 I hope this helps to give a better idea of what I'm trying to do. 0 Share this post Link to post Share on other sites
Naruto-kun 442 Report post Posted August 28, 2016 Looking over the output results, it appears that the x and y values of the vector after being multiplied by the inverse projection matrix are the angles to the pixel in radians (x converted to degrees is roughly -60 which fits with my horizontal FOV of 120 deg, and y is roughly 3.75 deg which fits my vertical FOV of 7.5 deg). I'm guessing the key is in what relationship the z and w values have with my far and near clip planes? 0 Share this post Link to post Share on other sites