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
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?