Я нарисовал конкретную сцену, используя определенную точку зрения (используя матрицы представлений и проекций). Я использовал VBO треугольников и так один. Я могу получить RGB изображения, используя:
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)
Но получение карты глубины вызывает какой-то странный результат, состоящий в основном из 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)
Я попытался заменить GL_UNSIGNED_BYTE
→ GL_FLOAT
и uint8
→ float32
Но это не помогло
Карта глубины инициализируется 1.0, что приводит к 255, если она считывается в буфер GL_UNSIGNED_BYTE
. Обратите внимание, что карта глубины находится в диапазоне [0.0, 1.0], если она читается GL_UNSIGNED_BYTE
, тогда этот диапазон отображается на [0, 255].
При перспективной проекции z-координата не линейно отображается в буфер глубины. Значение глубины быстро увеличивается, а геометрия, близкая к дальней плоскости, приведет к значению глубины значения 255.
Если у вас есть значение глубины в диапазоне [0.0, 1.0], и вы хотите вычислить координату z пространства зрения (глаза), тогда вам нужно преобразовать значение глубины в нормализованное устройство z координатный кулак (z_ndc
):
z_ndc = 2.0 * depth - 1.0;
Эта координата может быть преобразована в координату z пространства глаз (z_eye
) по следующей формуле:
z_eye = 2.0 * n * f / (f + n - z_ndc * (f - n));
где n
- ближайшая плоскость, f
- дальняя плоскость.
Обратите внимание, что это преобразование работает только для перспективной проекции.
При ортографической проекции координата z линейно отображается на глубину. Таким образом, обратное преобразование намного проще:
z_eye = depth * (f-n) + n;
См. Также Как визуализировать глубину линейно в современном OpenGL с gl_FragCoord.z в шейдере фрагмента?
GL_UNSIGNED_BYTE
. Обратите внимание, что карта глубины находится в диапазоне [0.0, 1.0], если она читается вGL_UNSIGNED_BYTE
, то этот диапазон отображается на [0, 255]