Ну, не совсем понятно, что вы имеете в виду под "пространством усеченного конуса".Я собираюсь предположить, что это относится к нормализованным координатам устройства в OpenGL, где усеченный вид (по умолчанию) - выровненный по оси куб -1 <= x,y,z <= 1
.Я также собираюсь предположить перспективную проекцию, так что координата NDC z
на самом деле является гиперболической функцией пространства глаза z
.
Я предполагаю, чтостандартная матрица проекции каким-то образом избавляется от некоторой важной информации о глубине, но кроме этого я понятия не имею, что я делаю неправильно и как это исправить.
Нет, стандартная матрица перспективы в OpenGL выглядиткак
( sx 0 tx 0 )
( 0 sy ty 0 )
( 0 0 A B )
( 0 0 -1 0 )
Когда вы умножаете это на (x,y,z,1)
пространство глаза, вы получаете однородные координаты клипа.Рассмотрим только последние две строки матрицы как отдельные уравнения:
z_clip = A * z_eye + B
w_clip = -z_eye
Поскольку мы делим перспективу, делим ее на w_clip
, чтобы добраться от пространства клипа до НДЦ, мы получаем
z_ndc = - A - B/z_eye
, которая на самом деле является информацией о глубине, переназначенной гиперболически, так что информация полностью сохраняется.(Также обратите внимание, что мы делаем деление также для x
и y
).
Когда вы вычисляете inverse(P)
, вы инвертируете только 4D -> 4D однородное отображение.Но в результате вы получите w
, который снова не будет 1
, поэтому здесь:
coordinates_worldspace = (inverse(V) * inverse(P) * vec4(vertexPosition_worldspace,1)).xyz;
^^^
- ваша потеря информации.Вы просто пропускаете получившиеся w
и используете компоненты xyz
, как если бы это были декартовы трехмерные координаты, но они являются 4D-однородными координатами, представляющими некоторую трехмерную точку.
Правильный подход - разделить на w
:
vec4 coordinates_worldspace = (inverse(V) * inverse(P) * vec4(vertexPosition_worldspace,1));
coordinates_worldspace /= coordinates_worldspace.w