glsl sampler2DShadow и shadow2D уточнение

Краткая справка о том, где я нахожусь (чтобы убедиться, что мы на одной странице, и проверить работоспособность, если я упускаю / предполагаю что-то глупое):

  • Цель: я хочу визуализировать мою сцену с тенями, используя отложенное освещение и карты теней.
  • Борьба: поиск четкой и последовательной документации о том, как использовать shadow2D и sampler2DShadow.

Вот что я сейчас делаю:

В фрагментном шейдере моего последнего прохода рендеринга (тот, который фактически вычисляет окончательные значения фрагмента) у меня есть матрицы MVP из прохода с точки зрения света, текстура глубины из указанного прохода (также известная как «карта теней»), и текстуры положения / нормали / цвета из моего буфера геометрии.

Насколько я понимаю, мне нужно найти, какому UV на карте теней соответствует положение текущего фрагмента. Я делаю это следующим образом:

//Bring position value at fragment (in world space) to screen space from lights POV
vec4 UVinShadowMap = (lightProjMat * lightViewMat * vec4(texture(pos_tex, UV).xyz,1.0)).xy; 
//Convert screen space to 'texture space' (from -1to1 to 0to1)
UVinShadowMap = (UVinShadowMap+1)/2;

Теперь, когда у меня есть этот УФ, я могу получить воспринимаемую «глубину» от точки обзора света с помощью

float depFromLightPOV = texture2D(shadowMap, UVinShadowMap).r;

и сравните это с расстоянием между позицией текущего фрагмента и источником света:

float actualDistance = distance(texture2D(pos_tex, UV).xyz, lightPos);

Проблема заключается в том, что «глубина» хранится в значениях 0–1, а фактическое расстояние - в мировых координатах. Я пытался выполнить это преобразование вручную, но не смог заставить его работать. И при поиске в Интернете мне СЛЕДУЕТ делать это с помощью sampler2DShadow ...


Итак, вот мои вопросы:

Какие изменения мне нужно внести, чтобы вместо этого использовать shadow2D? Что вообще делает shadow2D? Это просто более или менее автоматическое преобразование текстуры из глубины в мир? Могу ли я использовать такую ​​же глубину текстуры? Или мне нужно отрендерить текстуру глубины по-другому? Что мне передать в shadow2D? Положение фрагмента в мировом пространстве, который я хочу проверить? Или такой же УФ как раньше?

Если бы на все эти вопросы можно было ответить на простой странице документации, я бы хотел, чтобы кто-нибудь мог просто опубликовать это. Но я клянусь, что искал часами и не смог найти ничего, что просто говорило бы, что, черт возьми, происходит с shadow2D!

Спасибо!


person Phildo    schedule 15.03.2014    source источник
comment
Возможно, вы захотите посмотреть ответ на stackoverflow .com / questions / 19516538 /, поскольку он объясняет многие вопросы, о которых вы спрашиваете.   -  person user3256930    schedule 15.03.2014
comment
Я думаю, что этот вариант ближе (и вместе со ссылкой на вики в ответе должен отвечать на ваши вопросы): stackoverflow.com/questions/20877938/ (обратите внимание, что заголовок вопроса вводит в заблуждение - sampler2dshadow не является устаревшим)   -  person GuyRT    schedule 15.03.2014


Ответы (1)


Прежде всего, какую версию GLSL вы используете?

Начиная с GLSL 1.30, нет специальной функции поиска текстуры (все равно имя) для использования с sampler2DShadow. GLSL 1.30+ использует набор перегрузок texture (...), которые выбираются на основе типа переданного sampler и размеров координат.

Во-вторых, если вы все же используете sampler2DShadow, вам нужно сделать две вещи по-разному:

  1. Сравнение текстур должно быть включено, иначе вы получите неопределенные результаты

    • GL_TEXTURE_COMPARE_MODE = GL_COMPARE_REF_TO_TEXTURE​

  2. Координаты, которые вы передаете texture (...), являются трехмерными, а не двумерными. Новая 3-я координата - это значение глубины, которое вы собираетесь сравнивать.

Наконец, вы должны понимать, что возвращает texture (...) при использовании sampler2DShadow:

Если это сравнение прошло успешно, texture (...) вернет 1,0, если не удастся, вернет 0,0. Если вы используете фильтр текстуры GL_LINEAR для текстуры глубины, тогда texture (...) выполнит 4 сравнения глубины с использованием 4 ближайших значений глубины в текстуре глубины и вернет значение где-то посередине 1.0 и 0,0, чтобы дать представление о количестве пройденных / неуспешных выборок.

Это правильный способ аппаратного сглаживания теневых карт. Если вы попытаетесь использовать обычный sampler2D с GL_LINEAR и выполнить тест глубины самостоятельно, вы получите обратно одну усредненную глубину и логический результат «годен / не годен» вместо поведения, описанного выше для sampler2DShadow.


Что касается получения значения глубины для проверки из положения в мировом пространстве, вы были на правильном пути (хотя вы забыли о делении перспективы).

Есть три вещи, которые вы должны сделать, чтобы получить глубину из положения в мировом пространстве:

  1. Умножьте положение в мировом пространстве на вашу (световую) матрицу проекции и обзора.
  2. Разделите полученную координату на ее W компонент.
  3. Масштабируйте и смещайте результат (который будет в диапазоне [-1,1]) в диапазоне [0,1]

Последний шаг предполагает, что вы используете диапазон глубины по умолчанию ... если вы не вызывали glDepthRange (...), это сработает.

Конечный результат шага 3 служит как как значение глубины (R), так и координаты текстуры (ST) для загляните в свою карту глубины. Это позволяет передать это значение напрямую в texture (...). Напомним, что первые 2 компонента координат текстуры такие же, как всегда, а третий - это значение глубины для тестирования.

person Andon M. Coleman    schedule 15.03.2014
comment
Я знаю, что не должен просто комментировать. Спасибо, но серьезно - СПАСИБО! Я боролся с этим около месяца, и этот пост, наконец, помог мне преодолеть спад! Понятно, лаконично, все в одном месте. Блестяще. :) - person Phildo; 17.03.2014
comment
Почему тогда для вызова textureLod (sampler2DShadow) требуется vec4 для параметра p? Я ожидал (уф, глубина) ... что ты делаешь с vec4? - person ChaoSXDemon; 27.06.2017
comment
Будьте осторожны, используя как sampler2D, так и sampler2DShadow в одном шейдере. Их нельзя привязать к одному текстурному блоку. Вы также ДОЛЖНЫ инициализировать sampler2DShadow, если используете шейдер, который его объявляет (независимо от того, используется он на самом деле или нет). Причина в том, что по умолчанию он получает блок 0, и в зависимости от драйвера OpenGL выдаст предупреждение о том, что текстура 0 не является текстурой глубины, но вы используете sampler2DShadow. Хотя это можно проигнорировать, рекомендуется убедиться, что он инициализирован. - person ChaoSXDemon; 01.07.2017
comment
И какой фрагментный шейдер мне нужно использовать, если я просто хочу визуализировать карту глубины с помощью фильтра GL_LINEARtexture? Я имею в виду, что мне не нужны тени, а я только визуализирую глубину с помощью sampler2DShadow. - person Alexey S.; 30.03.2018