Эта строка объявляет новую переменную tnorm для сохранения значений преобразованной нормали (в OpenGL, как и в C++, можно объявлять переменные непосредственно перед использованием). Входные значения нормали (gl _Normal, встроенная переменная для доступа к значениям нормали) преобразуются с помощью матрицы преобразования нормали, определенной в OpenGL (gl_Normal Matri х). Вектор, полученный в результате преобразования, нормализуется, то есть приводится к вектору единичной длины, встроенной функцией normalize, и результат нормализации сохраняется в tnorm.
Затем вычисляется вектор из заданной точки на поверхности трехмерного объекта до источника освещения. Оба аргумента должны быть определены в пространстве координат обзора (это значит, что приложение должно задать значения uniform-переменной LightPosition в пространстве координат обзора). Вычисление вектора направления освещения происходит так: vec3 lightVec = normalize(L1ghtPosition - ecPosition): Заранее определенные координаты объекта в пространстве обзора находятся в scPosi ti on. Чтобы вычислить вектор направления освещения, нужно вычесть координаты объекта из координат источника освещения. Результат вычислений также приводится к единичному вектору и сохраняется в переменной 1 i ghtVec.
Проведенные вычисления - подготовка к использованию встроенной функции reflect. Из преобразованной нормали поверхности и вычисленного вектора освещения можно получить вектор отражения от поверхности объекта; функция reflect требует вектор освещения (направление от источника освещения к поверхности), и так как мы вычислили направление от поверхности к источнику освещения, вектор li ghtVec просто инвертируется: vec3 reflectVec = reflect(-1ightVec. tnorm); Так как оба вектора, используемые в этой операции, - единичные, то результирующий вектор также будет единичным. Чтобы завершить вычисление освещения, нужен еще один вектор - единичный вектор, определяющий направление обзора. Так как по определению точка обзора является началом координат (0,0,0) в пространстве координат обзора, нужно всего лишь инвертировать и привести к единичному вектору вычисленные координаты в пространстве обзора (ecPosition):
vec3 viewVec = normalizeC-ecPosition); С вычисленными векторами уже можно вычислять освещение конкретной вершины. Соотношения этих векторов показаны на рис. 6.2.
Рис, 6.2. Векторы для вычисления освещения в вершинном шейдере кирпичной стены
Рассеянное отражение создается следующим образом: допускается, что падающий на поверхность луч света рассеивается во все стороны по принципу распределения по функции косинуса. Отражение света будет наибольшим при совпадении вектора направления освещения и нормали поверхности. С увеличением угла до 90° рассеянное отражение будет уменьшаться до нуля. Так как оба вектора - единичные, косинус угла между li ghtVec и tnorm определяется их скалярным произведением. Чтобы рассеянное отражение было нулевым при угле между направлением освещения и нормалью поверхности больше 90° (то есть когда источник освещения расположен с обратной стороны объекта), используется функция шах: