DirectionalLigbtd, normal, amb. diff, spec); else if (gl_LightSource[i].spotCutoff == 180,0)
PointL1ght(i. eye, ecPosition3, normal, amb, diff. spec): else
SpotLight(i. eye, ecPosition3. normal, amb, diff. spec);
}
color = gl_BackLightModelProduct.sceneColor + amb * gl_BackMaterial.ambient + diff * glBackMaterial.diffuse;
if (SeparateSpecular)
gIBackSecondaryColor = vec4 (spec *gl_BackMaterial .specular, 1.0): else
color +■= spec * gl_BackMaterial .specular: gl_BackColor = color; Нет необходимости ограничивать значения gl_BackSeconeta ryCol or и gl_BackCol or, потому что это выполняется автоматически.
.5. Отсутствие освещения
Если ни один источник освещения не включен, можно просто передать первичный и вторичный цвета вершины дальше (листинг 9.14).
Листинг 9.14. Установка значений цвета без освещения
1f (SecondaryColor).
gl_FrontSecondaryColor = gl_SecondaryColor;
// Для gl_FrontColor ограничение будет выполнено автоматически gl_FrontColor - gl_Color:
9.6. Эффект дымки
В OpenGL эффекты глубины и дымки (туман, а в большинстве изображений просто ухудшение видимости с удалением предметов от точки обзора) контролируются параметрами дымки. Коэффициент дымки вычисляется с помощью одного из трех уравнений, а в дальнейшем используется при вычислении плавного перехода между цветом дымки и цветом фрагмента. Значение глубины, которое используется в выражении для дымки, может быть либо координатой дымки, переданной как стандартный атрибут вершины (gl_FogCoord), либо расстоянием от точки обзора до фрагмента изображения в пространстве координат обзора. Во втором случае обычно достаточно просто аппроксимировать значение глубины, используя абсолютное значение координаты z в пространстве обзора (то есть abs(ecPosition.z)). При очень большом угле обзора такая аппроксимация может спровоцировать заметный дефект изображения (небольшую дымку у края). В этом случае можно вычислять z как расстояние от точки обзора до фрагмента (1 ength(ecPosi ti on)). (Этот метод предполагает вычисление квадратного корня, что немного ухудшит производительность.) Выбрать способ вычисления в вершинном шейдере можно так:
if (UseFogCoordinate)
gl_FogFragCoord = gl_FogCoord; е!зе
gl_FogFragCoord = abs(ecPosition.z); Листинг 9.15. Вычисления дымки no GLJJNEAR
fog = (gl_Fog.end - gl_FogFragCoord)) * gl_Fog.scale: Так как 1.0 / (gl_Fog.end - gl_Fog.start) не зависит от состояния вершины или фрагмента, это значение можно вычислить заранее и сделать доступным в виде встроенной переменной gl_Fog. scale.
Более реалистичного эффекта дымки можно достичь с помощью экспоненциальной функции. Используя отрицательное значение экспоненты, экспоненциальная функция моделирует убывание изначального цвета в зависимости от расстояния. Простая экспоненциальная функция дымки выбирается в OpenGL с помощью константы GL__EXP, Язык шейдеров OpenGL не имеет встроенной функции expCbase е), но в нем есть экспоненциальная функция с основанием 2, ехр2. Учитывая, что ехр(х) = ехр 2{х/ lqg(2)), можно получить нужный результат. Выражение l/log(2) равно 1,442695. Код шейдера OpenGL для вычисления приведенного уравнения показан в листинге Э.16.