Глава б. Пример простого шейдера произведением. Чтобы рассеянное отражение было нулевым при угле между направлением освещения и нормалью поверхности больше 90° (то есть когда источник освещения расположен с обратной стороны объекта), используется функция max: float diffuse = maxCdotClightVec. tnorm). 0.0): Компонент зеркального отражения для вершины вычисляется так:
float spec - 0.0: if (diffusé > 0.0) {
spec = max(dot(reflectVec. vîewVec), 0.0); spec = paw С spec. 16,0):
}
Переменная для значения зеркального отражения определена и инициализирована нулем. Здесь будет вычисляться только значение отражения, отличное от нуля, если угол между нормалью и направлением освещения больше 90°, так как если источник освещения расположен за объектом, отражение света не происходит. Поскольку оба вектора, reflectVec и viewVec, - единичные, скалярное произведение (dot) этих двух векторов равняется косинусу угла между ними. Если угол близок к нулю (то есть вектор отражения и вектор обзора практически совпадают), результат будет приближаться к 1,0, Возведением результата в степень 16 в следующей строчке кода достигается усиление резкости изображения, и это приводит к тому, что ярко выраженное отражение света будет происходить только в области, где вектор отражения и вектор обзора практически совпадают. Число 16 в данном случае выбрано произвольно. При увеличении этого значения область отражения сужается, при уменьшении - расширяется, и отражение становится не таким концентрированным. Это значение можно сделать параметром шейдера, чтобы в приложении можно было задавать его через uniforni-переменную.
Осталось только умножить вычисленные значения рассеянного и прямого отражений на константы ai ffuseContri bution и specul а rContri but i on и сложить результаты:
tightlntensity = DiffuseContribution * diffuse + SpecularContribution * spec:
Результат будет занесен в переменную Lightlntensity и затем интерполирован между вершинами. Вычислить значение еще одой varying-переменной легко: