Реализация отображения теней в JavaScript и WebGL
Одной из наиболее важных функций для создания глубины и реализма в 3D-сцене являются тени. Они дают визуальные подсказки о форме и положении объектов. Тени также передают настроение и атмосферу.
Основным методом, используемым для рендеринга теней в 3D-приложениях в реальном времени, является отображение теней. Теневые объемы были альтернативой в прошлом, но в последние годы потеряли популярность по сравнению с гибкостью и простотой использования карт теней.
Картирование теней
Идея картирования теней довольно гениальна. Сцена визуализируется с точки зрения света в буфер кадра с прикрепленной текстурой глубины. Текстура глубины содержит самые близкие расстояния от света, и именно так тени работают и в реальной жизни. Листья дерева над вами ближе к солнцу, чем вы сами, а это значит, что листья находятся на солнце, а вы в тени. При использовании направленного света, такого как солнце, это делается с ортогональной проекцией, в то время как точечные источники света используют перспективную проекцию.
Следующим шагом будет рендеринг сцены на экран с несколькими дополнительными шагами в шейдерах. Вершинному шейдеру нужна матрица проекции представления модели карты теней, которая используется для вычисления координат тени каждой вершины:
#version 300 es layout( location = 0 ) in vec3 vertexPosition; uniform mat4 M_mvp; uniform mat4 M_shadowMap_mvp; out vec4 shadowCoord; void main() { gl_Position = M_mvp * vec4( vertexPosition , 1.0 ); shadowCoord = M_shadowMap_mvp * vec4( vertexPosition , 1.0 ); }
Во фрагментном шейдере координаты тени можно использовать для поиска значения текстуры глубины для каждого пикселя. Затем это значение можно сравнить с расстоянием фрагмента до источника света, и если значение глубины из карты теней больше, фрагмент освещен.
#version 300 es precision mediump float; in vec4 shadowCoord; uniform sampler2D shadowMap; out vec4 fragColor; void main() { float visibility = 0.0; float depthValue = texture( shadowMap …