Как использовать OpenGL ортографическую проекцию с буфером глубины? - PullRequest
3 голосов
/ 24 января 2012

Я отрисовал 3D-сцену в режиме перспективы glFrustum(). Затем у меня есть 2D-объект, который я помещаю поверх 3D-сцены, чтобы он действовал как метка для конкретного 3D-объекта. Я рассчитал 2D-положение 3D-объекта, используя gluProject(), в который я помещаю свой 2D-объект метки. 2D метка объекта визуализируется с использованием glOrtho() орфографического режима. Это прекрасно работает, и объект 2D-метки нависает над 3D-объектом.

Теперь я хочу дать 2D-объекту значение z, чтобы его можно было скрыть за другими 3D-объектами в сцене, используя буфер глубины. Я дал двумерному объекту значение z, которое, как я знаю, должно быть скрыто буфером глубины, но при рендеринге объекта оно всегда видно.

Итак, вопрос в том, почему 2D-объект все еще видим и не скрыт?

Я где-то читал, что ортогональные и перспективные проекции хранят несовместимые значения буфера глубины. Это правда, и если да, то как мне конвертировать между ними?

Ответы [ 2 ]

10 голосов
/ 24 января 2012

Я не хочу, чтобы он трансформировался, вместо этого я хочу, чтобы он отображался в виде плоской двумерной метки, которая всегда обращена к камере и всегда остается одинакового размера на экране. Однако, если оно скрыто за чем-то, я хочу, чтобы оно было скрыто.

Во-первых, вы должны были поставить , что в вашем вопросе; это объясняет гораздо больше о том, что вы пытаетесь сделать, чем ваш вопрос.

Для этого вам нужно найти координату z в ортографической проекции, которая совпадает с координатой z в предпроективном пространстве того места, где должна отображаться метка.

Когда вы использовали gluProject, вы получили три координаты назад. Координата Z важна. Что вам нужно сделать, это обратное преобразование координаты Z на основе значений zNear и zFar, которые вы задаете для glOrtho.

Педантическое примечание: gluProject не преобразует координату Z в пространство окна. Для этого необходимо принять параметры glDepthRange. Что он на самом деле делает, так это принимает диапазон глубины около 0,0 и далеко = 1,0.

Итак, наш первый шаг - преобразование из пространства Z окна в пространство Z нормализованной координаты устройства (NDC). Мы используем это простое уравнение:

ndcZ = (2 * winZ) - 1

Достаточно просто. Теперь нам нужно перейти в пространство клипа. Что является недопустимым, поскольку в ортографической проекции координата W принимается равной 1,0. А деление на W - это разница между пространством клипа и пространством NDC.

clipZ = ndcZ

Но нам не нужно пространство клипа Z. Нам нужно пространство доортографической проекции Z (иначе: пространство камеры Z). А для этого нужны параметры zNear и zFar, которые вы задали для glOrtho. Чтобы попасть в пространство камеры, мы делаем это:

cameraZ = ((clipZ + (zFar + zNear)/(zFar - zNear)) * (zFar - zNear))/-2

И все готово. Используйте эту позицию Z в вашем рендеринге. Да, и убедитесь, что ваша матрица вида модели не содержит каких-либо преобразований в направлении Z (если только вы не используете матрицу вида модели для применения этой позиции Z к метке, что нормально).

1 голос
/ 26 января 2012

Основываясь на ответе Николя, вы можете просто установить zNear на 0 (что обычно имеет смысл для 2D-элементов, которые действуют как часть GUI), и тогда вы просто получите:

cameraZ = -winZ*zFar
...