11.1.2. Фрагментный шейдер полосок Фрагментный шейдер содержит алгоритм для рисования полосок процедурным способом. Он приведен в листинге 11.2.
Листинг 11.2. Фрагментный шейдер для рисования полосок
uniform vec3 StripeColor;
uniform vec3 BackColor:
uniform float Width:
uniform float Fuzz:
uniform float Scale:
varying vec3 DiffuseColor: varying vec3 SpecularColor;
void main(void) {
11.1. Повторяющиеся шаблоны
float scaled!" - fract(gl_TexCoonJ[0].t * Scale);
float fracl = clamp(scaledT / Fuzz, 0.0. 1.0);
float frac2 = clampt(scaledT - Width) / Fuzz. 0.0. 1.0);
fracl - fracl * (1.0 - frac2);
fracl = fracl * fracl * (3.0 - (2.0 * fracl)):
vec3 finalColor = mixCBackColor. StripeColor. fracl): finalColor = finalColor * DiffuseColor + SpecularColor:
gl_FragColor = vec4 (finalColor. 1.0);
}
Еще одна uniform-переменная, передаваемая приложением, - Fuzz. Ее значение используется для создания плавности перехода (то есть сглаживания) между цветом полоски и цветом фона. При значении Scale 10,0 приемлемое значение Fuzz будет 0,1. С изменением размеров объекта значение Fuzz можно изменять, чтобы не допустить лишней расплывчатости при большом увеличении. Это значение на самом деле не должно быть больше 0,5 (максимальное размытие края полоски).
Сначала в шейдере выполняется умножение входной текстурной координаты t на масштаб полосок и отделение дробной части результата. Так можно вычислить координаты фрагмента внутри шаблона полосок. Чем больше значение Scale, тем больше полосок получится. Окончательное значение локальной переменной scaledT будет находиться в диапазоне [0, 1).
Переходы между цветами должны быть хорошо сглажены. Один из способов это сделать - использовать функцию smoothstep при переходе от StripeColor KBackColor, а потом еще раз - при переходе от BackColor к StripeColor. Но шейдер учитывает тот факт, что эти переходы симметричны, и совмещает два перехода в один.
Чтобы выполнить совмещение, значение scaledT используется для вычисления двух других значений: fracl и f гас2. Эти два значения сообщают, где находится текущая точка по отношению к переходам от BackCol or в St ri peCol or и обратно. Если scaledT/Fuzz больше 1, для fracl это означает, что точка находится вне зоны перехода, и значение приводится к 1, Если scaledT меньше Fuzz, то sealedT/Fuzz обозначает относительное расстояние от фрагмента до границы зоны перехода. Такое же значение вычисляется для другой стороны полоски вычитанием Width из scaledT, деленного на Fuzz, приведением результата к ширине зоны перехода и сохранением его в frac2.