хранение информации о глубине вершин в текстуре в теневом отображении opengl - PullRequest
4 голосов
/ 19 июля 2011

В настоящее время я программирую отображение теней (точнее, каскадное отображение теней) в мой движок c ++ opengl.Поэтому я хочу иметь текстуру, содержащую расстояние между моим источником света и каждым пикселем в моей карте теней.Какой тип текстуры я должен использовать?

Я видел, что существует внутренний формат текстуры GL_DEPTH_COMPONENT, но он масштабирует данные, которые я хочу дать текстуре, до [0,1].Должен ли я инвертировать мою длину один раз при создании карты теней, а затем второй раз во время окончательного рендеринга, чтобы вернуть реальную длину?Это кажется совершенно бесполезным!

Есть ли способ использовать текстуры для хранения длин без инвертирования их 2 раза?(один раз при создании текстуры, один раз при ее использовании).

1 Ответ

4 голосов
/ 21 июля 2011

Я не уверен, что вы имеете в виду под инвертированием (я уверен, что вы не можете инвертировать расстояние, поскольку это не сработает). Что вы делаете, это преобразовывает расстояние до источника света в диапазон [0,1].

Это можно сделать, построив обычную проекционную матрицу для вида источника света и применив ее к вершинам на этапе построения карты теней. Таким образом, их расстояние до источника света записывается в буфер глубины (к которому вы можете подключить текстуру в формате GL_DEPTH_COMPONENT с помощью glCopyTexSubImage или FBO). На последнем этапе вы, конечно, используете ту же матрицу проекции для вычисления координат текстуры для карты теней, используя проективное текстурирование (используя сэмплер sampler2DShadow при использовании GLSL).

Но это преобразование не является линейным, поскольку буфер глубины имеет более высокую точность вблизи зрителя (или источника света в этом случае). Другим недостатком является то, что вы должны знать действительный диапазон значений расстояния (самая дальняя точка, на которую влияет ваш источник света). Используя шейдеры (которые, как я полагаю, вы делаете), вы можете сделать это преобразование линейным, просто разделив расстояние до источника света на это максимальное расстояние и вручную назначив его для значения глубины фрагмента (gl_FragDepth в GLSL), которое вы и используете. вероятно, подразумевается под "инвертировать".

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

Подводя итог, можно сказать, что GL_DEPTH_COMPONENT - это просто хороший компромисс между убайтовыми текстурами (которым не хватает необходимой точности, так как GL_DEPTH_COMPONENT должна иметь точность не менее 16 бит) и плавающими текстурами (которые не так быстро или полностью поддерживаются в старое оборудование). Но из-за его формата с фиксированной запятой вы не сможете обойтись без преобразования [0,1] (будь то линейное или проективное). Я не уверен, что текстуры с плавающей запятой будут быстрее, так как вы сэкономите только одно деление, но если вы используете новейшее аппаратное обеспечение, поддерживающее линейную (или даже трилинейную) фильтрацию текстур с плавающей точкой и 1 или 2 компонентных текстур с плавающей точкой и целей рендеринга, возможно, стоит попробовать.

Конечно, если вы используете конвейер с фиксированной функцией, у вас есть только GL_DEPTH_COMPONENT в качестве опции, но в отношении вашего вопроса я предполагаю, что вы используете шейдеры.

...