Значения Bri ckPct. х и Bri ckPct. у можно вычислить приложением, чтобы получить ширину промежутков между кирпичами в обоих направлениях, основываясь на соотношении высоты ряда и ширины столбца; эти значения можно выбирать и произвольно.

Остается только вычислить окончательное значение цвета и сохранить его в особой переменной д! _/гадСо1 or:

color “ mixtMortarColor. BrickColor, useBrick.x * useBrick.y): color *= Lightlntensity;

gl_Frag.Color = vec4 (color. 1.0):

}

Периодическая функция шага для горизонтального компонента шаблона кирпичной стены

Рис. 6.3, Периодическая функция шага для горизонтального компонента шаблона кирпичной стены

Здесь цвет фрагмента вычисляется и сохраняется в локальной переменной col or. Встроенная функция mi х используется для выбора цвета кирпича или промежутка в зависимости от результата useBrick.х * useBrick.у. Так как useBrick.х и useBri ck. у могут иметь значения только 0 или 1,0, цвет кирпича можно получить, только если оба значения - 1,0, а иначе в результате получится цвет промежутка.

Затем вычисленное значение умножается на интенсивность освещения, и результат сохраняется в локальной переменной col ог. Эта переменная - типа vec3, a gl_FragColor определен как vec4, так что окончательное значение цвета будет получено с помощью конструктора. Он добавит четвертый компонент (прозрачность), равный 1,0, и занесет результат во встроенную переменную gl_FragCo1 or. Весь исходный код фрагментного шейдера приведен в листинге 6.2.

Листинг 6.2. Исходный код фрагментного шейдера кирпичной стены

uniform vec3 BrickColor, MortarColor; uniform vec2 BrickSize; uniform vee2 BrickPct:

varying vec? MCposition; varying float Lightlntensity:

void main(void)

{

vec3 color;

vec2 position. useBrick:

position = MCposition / BrickSize:

if (fract(position.y * 0.5) > 0.5) position.x +- 0.5;

position = fract(position);

useBrick = step(position. BrickPct);

eolor = mixCMortarCalor. BrickColor. useBrick.x * useBrick.y).; color *= LightIntensity; gl_FragColor = vec4 (color. 1.0);

'I

При сравнении этого шейдера с вершинным шейдером из предыдущего примера видно, что основные возможности языка шейдеров OpeijGL, использованные в них, почти одинаковы. Оба шейдера используют функцию Tain, некоторые umform-переменныс, некоторые локальные переменные, выражения; встроенные ..функции вызываются одинаково; конструкторы используются одинаково и т. д. Небольшие различия заключаются в следующем: а) вершинный шейдер работает .свстроенными атрибутами gl_Vertex и gl_Normal; б) вершинный шейдер пишет во встроенную переменную gl_Position, в то время как фрагментный шейдер пишет во встроенную переменную gl FragCol or; в) varying-переменные устанавливаются в вершинном шейдере и считываются фрагмеитным шейдером.

Код приложения, в котором создаются и используются эти шейдеры, приведен в разделе 7.11 после описания API языка шейдеров OpenGL. Результат рендеринга нескольких простых объектов показан на рис. 6.4 (см. также цветной рис. 25).

Плоский многоугольник, шар и тор, рендеринг которых выполнялся шейдерами кирпичной стенки

Рис. 6.4. Плоский многоугольник, шар и тор, рендеринг которых выполнялся шейдерами кирпичной стенки

6.4. Замечания

В приведенном решении задачи есть несколько подводных камней, из-за которых оно может использоваться только в самых простых случаях. Так как шаблон кирпичной стены вычисляется с использованием модельных координат заданного объекта, видимые размеры кирпичей зависят от размера объекта в модельных координатах. Некоторые объекты в результате будут выглядеть хорошо, но для других созданные нами кирпичики будут либо слишком большими, либо слишком маленькими. Чтобы избежать этого, для вершинного шейдера нужно задать параметр - uniform-переменную, в соответствии со значением которой шаблон будет масштабироваться по отношению к модельным координатам. Приложение могло бы предоставлять пользователю возможность самому задавать масштаб для того, чтобы кирпичный рисунок выглядел хорошо на любом объекте.


⇐ вернуться назад | | далее ⇒