2

I have drawn a specific scene using from a specific point of view (using view and projection matrices). I used VBOs of triangles and so one. I can get the RGB of the image using:

data = glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE)
data = np.frombuffer(data, dtype=np.uint8).reshape(width, height, 3)[::-1]
cv2.imwrite(r"c:\temp\image1.png", data)

But getting the depth map gets some strange result that consists mostly of 255:

data2 = glReadPixels(0, 0, width, height, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE)
data2 = np.frombuffer(data2, dtype=np.uint8).reshape(width, height)[::-1]
cv2.imwrite(r"c:\temp\image2.png", data2)

I tried replacing GL_UNSIGNED_BYTE -> GL_FLOAT and uint8 -> float32

But that didn't help

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
user972014
  • 3,296
  • 6
  • 49
  • 89
  • 1
    *"But getting the depth map gets some strange result that consists mostly of 255"* - What is so strange? The depth map is initialized by 1.0, which leads to 255 if it is read to a `GL_UNSIGNED_BYTE` buffer. Note the depth map is in range [0.0, 1.0], if it is read to `GL_UNSIGNED_BYTE`, then this range is mapped to [0, 255] – Rabbid76 Aug 27 '18 at 10:16
  • The strangeness is that it completely doesn't reflect what is drawn in the scene. The scene is "full" (triangles are drawn all over the image, with no "blank" spaces). Also - The values that are not 255, are very close to it – user972014 Aug 27 '18 at 10:55
  • Do you use perspective projection? Note, the z-coordinate is no linearly mapped to the depth buffer at perspective projection. The depth value rapidly increases and geometry which is close to the far plane will lead in an value depth value of 255. See [How to render depth linearly in modern OpenGL with gl_FragCoord.z in fragment shader?](https://stackoverflow.com/questions/7777913/how-to-render-depth-linearly-in-modern-opengl-with-gl-fragcoord-z-in-fragment-sh/45710371#45710371) – Rabbid76 Aug 27 '18 at 11:53
  • It seems that the problem was me having near and far plane values that were wrong (0.01 -> 100) Which caused everything at a distance of around 5-10 to have very high values. I change the near value to 1.0 and change the call to get GL_FLOAT (and not GL_UNSIGNED_BYTE), and now I get values that seem reasonable and match the scene. But currently I don't understand how to translate this 0.0->1.0 values to the true depth. – user972014 Aug 27 '18 at 12:02
  • What do you mean by the "true" depth? Do you mean the view (eye) space z-coordinate? – Rabbid76 Aug 27 '18 at 12:04
  • Yes, that's what I mean – user972014 Aug 27 '18 at 12:05
  • 1
    Again see [How to render depth linearly in modern OpenGL with gl_FragCoord.z in fragment shader?](https://stackoverflow.com/questions/7777913/how-to-render-depth-linearly-in-modern-opengl-with-gl-fragcoord-z-in-fragment-sh/45710371#45710371): `z_ndc = 2.0 * depth - 1.0;` `z_eye = 2.0 * n * f / (f + n - z_ndc * (f - n));`,where `n` is the near plane and `f` is the far plane. (for perspective projection!) – Rabbid76 Aug 27 '18 at 12:06
  • 1
    Thanks. That solved it. Please answer the question directly so I can mark it as correct – user972014 Aug 27 '18 at 12:28

1 Answers1

2

The depth map is initialized by 1.0, which leads to 255, if it is read to a GL_UNSIGNED_BYTE buffer. Note, the depth map is in range [0.0, 1.0], if it is read to GL_UNSIGNED_BYTE, then this range is mapped to [0, 255].

At perspective projection the z-coordinate is no linearly mapped to the depth buffer. The depth value rapidly increases and geometry which is close to the far plane will lead in an value depth value of 255.

If have got a depth value in the range [0.0, 1.0] and you want to calculate the the view (eye) space z coordinate, then you have to convert the depth value to the normalized device z coordinate fist (z_ndc):

z_ndc = 2.0 * depth - 1.0;

This coordinate can be transformed to the eye space z coordinate (z_eye), by the following formula:

z_eye = 2.0 * n * f / (f + n - z_ndc * (f - n));

where n is the near plane and f is the far plane.

Note, this transformation works for perspective projection only.

At orthographic projection, the z coordinate is linearly mapped to the depth. So the backwards transformation is much simpler:

z_eye = depth * (f-n) + n; 

See also How to render depth linearly in modern OpenGL with gl_FragCoord.z in fragment shader?

Rabbid76
  • 202,892
  • 27
  • 131
  • 174