Листинг 9.10 (продолжение)
diff = vec4 (0.0): spec = vec4 (0.0):
// Цикл по включенным источникам for (i =“ 0: i < NumEnabledLights: i++)
{
if (g1_LightSource[i].position.w == 0.0)
Di recti onalLightd, normal, amb, diff. spec): else if (gl__LightSource[i].spotCutoff = 180.0)
PoihtLightd. eye. ecPosition3, normal, amb. diff, spec); else
SpotLight(i. eye, ecPosition3, normal, smb. diff. spec):
}
Одна из дополнительных возможностей OpenGL 1.2 - функциональность для расчета цвета вершины за два этапа: сначала как обычно вычисляется первичный цвет, включая компоненты излучения, рассеяиия и отражения; затем вторичный цвет, который содержит только компонент зеркального отражения. Если этот режим не включен (по умолчанию), первичный цвет будет содержать все компоненты: излучения, рассеяния, отражения и зеркального отражения.
Вычисление зеркального отражения отдельно от остальных позволяет накладывать его после текстурирования. Значение зеркального отражения накладывается на вычисленный цвет после текстурирования для того, чтобы отраженный свет был окрашен в цвет источника освещения, а не в цвет поверхности. Вычисление цвета поверхности без компонента зеркального отображения показано в листинге 9.11.
Листинг9.11. Вычисление цвета поверхности без компонента зеркального отражения
color = gl_FrontLightModelProduct.sceneColor + amb * gl_FrontMaterial.ambient + diff * g!_FrontMaterial .diffuse; Язык шейдеров OpenGL предоставляет удобную встроенную переменную gl_ГrontLightModel Product. sceneColor, в которой содержится значение излучающего свойства материала для передних поверхностей и общее значение рассеянного освещения (то есть дЛ_FrontMaterial.emission + gl_FrontMaterial.ambient * gl _Li ghtHodel .ambi ent). Можно сложить его с интенсивностью отраженного света и интенсивностью рассеянного света. В дальнейшем нужно поступать в зависимости от того, указан ли режим отдельного наложения компонента зеркального отражения (листинг 9.12).
Листинг 9.12. Завершающие вычисления цвета поверхности
if (SeparateSpecular)
gl_FrontSecondaryColor = vec4 (spec *gl_FrontMaterlal.specular. 1.0); el se
color += spec * gl_FrontMaterial .specular; gl_FrontColor = color; Нет необходимости ограничивать значения (clamping) gl _FrontSecondaryColor и gl_FrontColor, так как это будет сделано автоматически.
А Двухстороннее освещение
Чтоб!»] в OpenGL имитировать двухстороннее освещение, нужно инвертировать нормаль поверхности и выполнить те же самые вычисления, что и в предыдущем разделе, но только со значениями задней поверхности материала. Возможно, при необходимости читатель выполнит такие вычисления более оптимально, а сама идея вычислений содержится в листинге 9.13.
Листинг 9.13. Вычисление двухстороннего освещения
normal = -normal:
11 Инициализация переменных для накопления интенсивности освещения amb = vec4 (0.0); diff - vec4 (0.0): spec - vec4 (0.0);
// Цикл no всем источникам, вычисление компонентов освещения от каждого for (1=0; i < NumEnabledLights: i++)
{
if (gl_LightSource[i].position.w == .0.0)