Отображение должно быть логарифмическим, что обеспечивает большую точность в ближнем поле.
На самом деле, если вы не выполните никаких трюков, отображение будет гиперболическим не логарифмический.Ключевым моментом в отношении гиперболического отображения является то, что вы можете на самом деле интерполировать его линейно в экранном пространстве (что является очень хорошим свойством, если вы хотите выполнить некоторые оптимизации Z-буфера, такие как Hierarchical Z).
Графикиз наиболее распространенной проекции OpenGL, которую я нашел в сети, которая должна отображаться от -1 до +1:
lambda z: ((-f+n)/(f-n)*z - 2*f*n/(f-n))/-z
Нет.У вас есть ошибка знака в первом члене, это должно быть
(-(f+n)/(f-n)*z - 2*f*n/(f-n))/-z
Следовательно, ваш сюжет просто неверен.С исправленной формулой вы получите сюжет, похожий на вашу cgmath
библиотеку ржавчины.
Но важная часть - это нечто другое: Вы замышляете не ту вещь !Обратите внимание на -z
на знаменателе в этой формуле?Классическим соглашением GL всегда было использование правостороннего глазного пространства, но левостороннего оконного пространства.В результате классическая проекционная матрица GL проецируется в направлении -z
.Параметры n
и f
все же задаются как расстояния вдоль направления просмотра.Это означает, что фактические плоскости отсечения будут в z_eye = -n
и z_eye=-f
в глазном пространстве.То, что вы наметили на графике, это диапазон позади камеры, и вы увидите вторую ветвь гиперболы, ту, которая обычно обрезана в любом направлении, и которая будет отображаться за пределами интервала [-1,1]
.
Если вы построите отображение для n = 5 и f = 100, вы получите:
Обратите внимание, что проект OpenGL в направлении -z
Чистое соглашение, оно ничем не навязывается, поэтому вы также можете использовать +z
матрицу проекций.
Я не могу построить правильную матрицу проекций Vulkan (из которых я не нашел ни одной)через гугл), если я не понимаю, что z должен отображаться.Вот график отображения z с использованием матрицы, которую я построил по спецификации Vulkan.Это приводит к ошибкам в рендеринге, но дает правильный результат, насколько я понимаю:
lambda z: (f / (f-n) * z - f*n/(f-n)) / z
Не уверен, какие ошибки вы видите с этим, но отображение корректно, если вы
- предполагают, что по умолчанию вулкан использует [0,1] z клипов, а
- хочет направление проекции вдоль
+z
в пространстве глаза.
Кстати.Соглашение о клипах vulkans [0,1]
также позволяет лучше использовать точность при использовании привязки глубины с плавающей запятой: изменив отображение так, чтобы ближняя плоскость была сопоставлена с 1, а дальняя плоскость была сопоставлена с 0, вы можете значительно повысить точность,Посмотрите эту статью по nvidia devblog для получения более подробной информации.