float diffuse = max(dot(1ightVec. tnorm). 0.0): Компонент зеркального отражения для вершины вычисляется так:
float spec ^0,0;
if (diffuse >0.0)
{
spec = max(dot(reflectVec. viewVec). 0.0); spec = pow(spec. 16.0);
}
Переменная для значения зеркального отражения определена и инициализирована нулем. Здесь будет вычисляться только значение отражения, отличное от нуля, если угол между нормалью и направлением освещения больше 90°, так как если источник освещения расположен за объектом, отражение света не происходит. Поскольку оба вектора, reflectVec и viewVec, - единичные, скалярное произведение (dot) этих двух векторов равняется косинусу угла между ними. Если угол близок к нулю (то есть вектор отражения и вектор обзора практически совпадают), результат будет приближаться к 1,0. Возведением результата в степень 16 в следующей строчке кода достигается усиление резкости изображения, и это приводит к тому, что ярко выраженное отражение света будет происходить только в области, где вектор отражения и вектор обзора практически совпадают. Число 16 в данном случае выбрано произвольно. При увеличении этого значения область отражения сужается, при уменьшении - расширяется, и отражение становится не таким концентрированным. Это значение можно сделать параметрам шейдера, чтобы в приложении можно было задавать его через uniform-перемениую.
Осталось только умножить вычисленные значения рассеянного и прямого отражений на константы di ffuseContri bution и specul arContri but i on и сложить результаты:
Lightlntensity = DiffuseContribution * diffuse +
SpecularContribution * spec; Результат будет занесен в переменную Lightlntensity и затем интерполирован между вершинами. Вычислить значение еще одой varying-переменной легко:
MCposition = glj/ertex.xy; Когда такой шаблон кирпичей уже наложен на геометрический объект, рисунок не должен сдвигаться по отношению к объекту, как бы ни менял свое расположение объект и как бы ни двигалась точка обзора. Чтобы совместить это требование с алгоритмическим вычислением рисунка поверхности во фрагментном шейдере, необходимо знать координаты каждого фрагмента, которые определяют его положение на поверхности объекта. В этом примере зададим модельные координаты каждой вершины, устанавливая varying-переменную HCposition в то же значение, что и исходные координаты вершины (которые по определению должны задаваться в пространстве координат объекта).
Во фрагментном шейдере ые используются координаты z или ®, так что нужен способ извлечь компоненты х и у из g!_Vertex. Мы могли бы использовать здесь конструктор (то есть написать vec2(gl_Vertex)), но, чтобы продемонстрировать еще одну возможность языка, выберем первые два компонента gl_Vertex (.ху) и затем сохраним их в переменной MCposition.
Единственное, что нам осталось, - вычислить однородные координаты вершины (это должен выполнять каждый вершинный шейдер). Это достигается преобразованием входных координат вершины с помощью матрицы модели -вида- щюекции с использованием встроенной функции ftrans.form-. gl_Position = ftransformO: