Угол азимута определяется проецированием направления отражения на плоскость XZ. Значение этого угла будет колебаться от 0 до 360°, и по этому значению можно определить вторую текстурную координату в диапазоне [0, 1].

Следующие OpenGL-шейдеры будут совместно выполнять наложение карты среды на объект. Углы возвышенности и азимута вычисляются для определения значений snt, которые, в свою очередь, используются для доступа к текстуре среды. Предполагается, что у объекта есть дополнительный слой, который рассеивает часть освещения. Результат этого рассеивания сочетается с отражением окружающей среды для получения окончательного значения каждого пиксела.

10.4.1. Подготовка приложения

Для использования этого шейдера приложение должно сделать не очень многое. Используется очень простая модель освещения, так что нужно передавать только координаты одного источника освещения. В данном примере карта окружения будет занесена в текстурный модуль 4. Режим наложения для текстуры устанавливается и для s, и для t (это необходимо для небольшого трюка во фрагментном шейдере). Цвет слоя, который рассеивает освещение, для данного объекта определяется в baseColor, а соотношение основного цвета к отражению среды устанавливается в mi xRati о. Вот определения необходимых uniform-переменных.

LightPos 0.0, 0.0. 4.0

BaseColor 0.4. 0.4. 1.0

MixRatio 0.8

EnvMap 4

После того как шейдеры, а также значения imiform-переменных установлены, приложение должно задать нормаль и координаты для каждой вершины. Текущие значения матрицы модели-вида, матрицы проекции-мод ели-вида и матрицы нормали будут получены непосредственно из шейдера.

10.4.2. Вершинный шейдер

В листинге 10.5 показан вершинный шейдер, который используется для наложения карты среды.

Листинг 10.5. Вершинный шейдер для наложения карты среды

varying vec3 Normal; varying vec3 EyeDir; varying float Lightlntensity;

uniform vec3 LightPos; void main(void)

{

gl_Position - ftransformO;

Normal = normalize(gl_NormalMatri;< * gl_Normal);

vec4 pos = g1_ModelViewHatrix * glj/ertex;

EyeDir •= pos.xyz;

Lightlntensity = max(dot(normalize(LightPos - EyeDir), Normal). 0.0);

}

Цель данного вершинного шейдера - получить три значения, которые будут интерполироваться для каждого примитива: значения рассеянного освещения, нормали поверхности и направление обзора. Два последних значения позволяют вычислить точное направление отражения для каждого фрагмента, а отсюда можно вычислить требуемые углы возвышенности и азимута.

Преобразованные координаты вершины вычисляются в первой строке программы обычным способом: преобразуется и нормализуется нормаль, затем е помощью текущей матрицы модели-вида и входных значений для вершины вычисляется направление обзора. Эти два значения потом будут использоваться во фрагментном шейдере, чтобы определить вектор отражения. И наконец, вычисляется значение рассеянного освещения таким же способом, как и в предыдущих примерах.


⇐ вернуться назад | | далее ⇒