Объект, изображенный на цветном рис. 13, представляет собой неполный тор, рендеринг которого выполнен шейдером полосок. Этот шейдер и приложение, использующее этот шейдер, разработаны в 2002 г. компанией LightWork Design, которая разрабатывает программное обеспечение для наложения фотореалистичных эффектов1 на объекты, созданные коммерческими автоматизированными пакетами (CAD/CAM). Приложения, разработанные LightWork Design, имеют графический интерфейс, который позволяет пользователю менять параметры шейдера. Имена доступных шейдеров перечислены в правом верхнем углу экрана, а параметры выделенного шейдера, которые можно изменять, - в правом нижнем. В нашем случае параметры для шейдера полосок - это цвет полоски (синий), цвет фона (оранжевый), масштаб (количество полосок) и ширина полоски (соотношение ширины полоски к ширине фонового просвета; если это значение, например, 0,5, синие и оранжевые полоски будут одинаковой ширины). На цветном рис. 12 показан снимок экрана с большим количеством объектов, рендеринг которых выполнен процедурными шейдерами OpenGL.
Для шейдера полосок приложение должно посылать только параметры вершин и текстурные координаты каждой вершины. Для того чтобы определить, какой цвет использовать во фрагменте - фона или полоски, используется текстурная координата t, а текстурная координата s не используется вообще. Приложение должно также передавать значения в вершинный шейдер для вычисленрш освещения. Указанные параметры - цвет полоски, фона, масштаб и ширина полоски - должны передаваться во фрагментный шейдер, так что полоски вычисляются для каждого фрагмента.
11.1.1. Вершинный шейдер полосок
Вершинный шейдер для эффекта полосок приведен в листинге 11.1.
Листинг 11.1. Вершинный шейдер для рисования полосок
uniform vec3 LightPosition: uniform vec3 LigbtColor: uniform vec3 EyePosition; uniform vec3 Specular: uniform vec3 Ambient: uniform float Kd;
varying vec3 DiffuseColor; Листинг 11,1 (продолжение)
varying vec3 Specular-Color:
void main(void)
{
vec3 ecPosition = vec3 Cg1_Mode1ViewMatrix * gl_Vertex): vec3 tnorm = normalize(gl_Norma1Matrix * gl_Normal); vec3 lightVec = normalize{LightPosition - ecPosition):
vec3 viewVec = normalize(EyePosition - ecPosition): vec3 hvec = normalize(viewVec + lightVec):
float spec = clamp(dot(.hyec. tnorm). 0.0. 1.0):
spec = powCspec. 16.0):
DiffuseColor - LightColor * vec3 (Kd * dotClightVec, tnorm)):
DiffuseColor = clampCAmbient + DiffuseColor. 0.0. 1.0):
SpecularColor = clamp((LightColor * Specular * spec). 0.0, 1.0):
gl_TexCoord[0] = gl_MultiTexCoordO: gl_Positien = ftransfcrmO;
}
В этом шейдере есть несколько интересных особенностей, но действительно ничего необычного. Это хороший пример такого вычисления освещения, которое было бы совместимо со множеством фрагментных Шейдеров.
Как уже упоминалось, значения для вычисления освещения (LightPosition, LightColor, EyePosition, Specular, Ambient и Kd) передаются приложением через uniform-переменные, Назначение этого шейдера - вычислять Di ffuseCol or и Specul ar-Col or, две varying-переменные, которые затем будут интерполированы для каждого примитива и переданы фрагментному шейдеру для каждого фрагмента. Эти значения вычисляются обычным способом, с небольшой оптимизацией - Arnbient добавляется к вычисленному значению рассеянного отражения, чтобы посылать во фрагментный шейдер через varying-переменную на одно значение меньше. Входные текстурные координаты передаются во фрагментный шейдер как встроенная vary-ing-перемеииая gl_TexCoord[0], и координаты вершины преобразуются как обычно.