// Нормализация вектора от поверхности до источника освещения VP = normalize(VP):
// Вычисление коэффициента поглощения
attenuation = 1.0 / (g1_LightSource[i].constantAttenuation + gl _LightSource[i].1inearAttenuati on * d + gl_LightSource[i],quadraticAttenuation * d * d):
// Проверка вхождения точки поверхности в конус света spotDot = dot С - VP, gl_LightSource[i].spotDire.ction):
if (spotDot < gl_LightSource[i].spotCosCutoff)
spotAttenuation = 0.0: // этот источник освещения не участвует
else
spotAttenuation =* pow(spotDot. gl_LightSource[i].spotExponent):
// Совмещение коэффициентов поглощения и расстояния
attenuation *= spotAttenuation; halfVector = normalize(VP + eye); nDotVP = max(0.0. dot(normal. VP)): nDotHV = max(0.0. dot(normal. halfVector));
if (nDotVP == 0.0) pf = 0.0: else
pf = pow(nDotHV. gl_FrontMaterial .shininess):
ambient += gl_LightSource[i],ambient:
diffuse +" gl_LightSource[i].diffuse * nDotVP * attenuation;
specular += gl_LightSourc.e[i].specular * pf * attenuation:
}
1.3. Свойства материала и освещение
Вычисление освещения в OpenGL требует знания направления обзора в системе координат обзора, чтобы вычислить элемент отражения. По умолчанию направление обзора принимается параллельным оси -г. В OpenGL есть режим, требующий определения направления обзора от начала координат в системе координат обзора. Чтобы сделать это, можно преобразовать входные координаты вершины в систему координат обзора с помощью текущей матрицы модели-вида. Координаты х,у иг точки обзора делятся на однородную координату w для получения значения vec3, которое и используется в дальнейших вычислениях. Вычисление этих координат обзора (ecPosi ti опЗ) показано в разделе 9.1. Для получения единичного вектора направления обзора нужно нормализовать и инвертировать координаты. Код шейдера, который это выполняет, показан в листинге 9.9.
Листинг 9.9. Вычисление координат наблюдателя
if (Local Vi ewer)
eye = -normalize(ecPosition3): else
eye = vec3 (0.0, 0.0. 1.0): После этого можно инициализировать переменные, которые затем будут использоваться для накопления составляющих рассеянного света, отражения и зеркального отражения от всех источников освещения. Можно использовать функции из предыдущего раздела, чтобы вычислить вклад в освещение каждого источника. В коде листинга 9.10 предполагается, что все источники освещения с номером, меньшим NumEnabl edLi ghts, включены. Источники направленного освещения имеют значение однородной координаты w равное 0 во время передачи этих координат в OpenGL (затем все переданные координаты преобразуются с помощью матрицы модели-вида, так что координата w после преобразования останется О, если последний столбец матрицы типичный (ООО 1)). У точечных источников освещения угол ограничения равен 180°.
Листинг 9.10. Цикл для вычисления суммарного освещения от всех источников
// Инициализация переменных для накопления интенсивности света arnb = vec4 (0.0):