gl_Position = ftransformO; Единственное различие между ними в следующем: второй способ гарантирует, что преобразование координат выполнялось точно таким же способом, как это делает стандартная функциональность. Некоторые реализации могут иметь собственные аппаратные усовершенствования, которые будут обусловливать небольшие различия в таких преобразованиях. Это может создавать проблемы при использовании многопроходных алгоритмов, где один и тот же алгоритм используется для рисования одних и тех же фигур более одного раза. В таких случаях предпочтительно применять второй метод, поскольку он работает точно так же, как стандартная функциональность.
Координаты источника освещения преобразуются с помощью матрицы моде-ли-вида при передаче их в OpenGL. Это значит, что сохраняются они в координатах обзора. Зачастую удобнее рассчитывать освещение в системе координат обзора, так что бывает необходимо сделать соответствующие преобразования (листинг 9.1).
Листинг 9.1. Вычисление координат точки обзора
vec4 ecPosition:
vec3 ecPosition3: // in 3 space
// Преобразование координат вершины в систему координат обзора
if (NeedEyePosition)
{
ecPosition = gl_Mode1Vi ewMatri x * gl_Vertex: ecPosition3 = (vec3 (ecPosition)) / ecPosition.w:
}
Этот фрагмент кода вычисляет однородную точку в системе координат обзора (vec4), а также неоднородную точку (vec3). Оба значения понадобятся в дальнейшем.
Чтобы рассчитать освещение в пространстве обзора, нужно также преобразовать нормали поверхности. Для доступа к матрице преобразований нормали существуют встроенные uniform-переменные (листинг 9.2).
Листинг 9,2. Преобразования нормали
normal = gl NormalMatrix * gl_Normal: Во многих случаях приложение может и не знать ничего о характеристиках нормалей поверхности. Чтобы убедиться в том, что освещение вычислено правильно, нужно нормализовать каждую входящую нормаль до единичной длины. В стандартной функциональности OpenGL нормализация - это параметр, который можно контролировать с помощью передачи символической константы GL_NORMALIZE в функции glEnable или glDisable. В шейдере OpenGL необходимая нормализация делается так, как в листинге 9.3.
Листинг 9.3. Нормализация нормали
normal = normalize(normal); Иногда приложение знает, что всегда будет посылать нормали в единичном виде, а матрица модели-вида будет применяться для масштабирования. В этом случае можно изменять масштаб, чтобы избежать «дорогой» операции извлечения квадратного корня. Коэффициенты масштабирования должны быть предоставлены приложением, и нормали могут быть масштабированы так, как показано в листинге 9.4.
Листинг 9.4. Масштабирование нормали
normal = normal * gl_NormalScale; Коэффициенты масштабирования сохраняются как состояние OpenGL, и к ним можно обращаться из шейдера, используя встроенную uniform-переменную gl _Norma 1 Seal е.
Координаты текстур также можно преобразовывать, Для каждого текстурного модуля в OpenGL определена текстурная матрица и к ней можно обращаться че рез встроенную uniform-переменную массива матриц gl_TextureMatrix. Входные координаты текстур преобразуются точно так же, как координаты вершин (листинг 9.5).