Вы не говорите, как вы создали свои значения глубины. Поэтому я предполагаю, что вы сгенерировали значения глубины, отрисовывая треугольники с помощью обычной проекции. То есть вы преобразуете геометрию в пространство камеры, преобразуете ее в пространство проекции и позволяете конвейеру растеризации обрабатывать вещи оттуда как обычно.
Чтобы сделать отображение теней, ваши текстурные координаты должны совпадать с тем, что делал растеризатор.
Вывод вершинного шейдера - это клип-пространство. Оттуда вы получите разрыв перспективы, сопровождаемый преобразованием области просмотра. Последний использует значения из glViewport и glDepthRange для вычисления XYZ пространства окна. Окно-пространство Z - это значение глубины, записанное в буфер глубины.
Обратите внимание, что это все во время прохода глубины: генерация значений глубины для карты теней.
Однако вы можете воспользоваться некоторыми сочетаниями клавиш. Если для вашего диапазона glViewport был установлен тот же размер, что и для текстуры (что обычно и делается), то вы можете игнорировать преобразование области просмотра. Вам все равно понадобится glDepthRange, который вы использовали в проходе глубины.
В своем фрагментном шейдере вы можете выполнить деление перспективы, которое помещает координаты в нормализованное пространство координат устройства (NDC). Это пространство [-1, 1] во всех направлениях. Ваши координаты текстуры [0, 1], поэтому вам нужно разделить X и Y на два и добавить к ним 0,5:
vec3 ndc_space_values = light_vert_pos.xyz / light_vert_pos.w
vec3 texCoords;
texCoords.xy = ndc_space_values.xy * 0.5 + 0.5;
Чтобы вычислить значение Z, вам нужно знать значения ближнего и дальнего расстояний, которые вы используете для glDepthRange
.
texCoords.z = ((f-n) * 0.5) * ndc_space_values.z + ((n+f) * 0.5);
Где n
и f
- значения ближнего и дальнего радиуса glDepthRange. Конечно, вы можете предварительно вычислить некоторые из них и передать их как униформу. Или, если вы используете диапазон по умолчанию вблизи = 0 и далеко = 1, вы получите
texCoords.z = ndc_space_values.z * 0.5 + 0.5;
Что выглядит как-то знакомо.
За исключением:
Поскольку вы определили свои входные данные с in
вместо varying
, вы должны использовать GLSL 1.30 или выше. Так почему вы используете texture2D
(это старая функция), а не texture
?