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) {

float scaled! - fractCgl_TexCoord[Q]-t * Scale);

float fracl = clamp(scflledT / Fuzz, 0.0. 1.0):

float frac2 = clamp((scaledT - Width) / Fuzz. 0.0. 1.0):

fracl - fracl * (1.0 - frac2);

fracl = fracl * fracl * (3.0 - (2.0 * fracl));

vec3 finalColor = mixCBackColor. StripeCslor. 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 jc BackColor, а потом еще раз - при переходе от BackColor к StripeColor. Но шейдер учитывает тот факт, что эти переходы симметричны, и совмещает два перехода в один.

Чтобы выполнить совмещение, значение scaledT используется для вычисления двух других значений: fracl и frac2. Эти два значения сообщают, где находится текущая точка по отношению к переходам от BackColor в StripeColor и обратно. Если sea 1 edT/Fuzz больше 1, для fracl это означает, что точка находится вне зоны перехода, и значение приводится к 1, Если scaledT меньше Fuzz, то seal edT/Fuzz обозначает относительное расстояние от фрагмента до границы зоны перехода. Такое же значение вычисляется для другой стороны полоски вычитанием Width из scaledT, деленного на Fuzz, приведением результата к ширине зоны перехода й сохранением его в frac2.

Полученные значения обозначают ширину размытой области. На одной из сторон полоски frac2будет равно 0, a fracl - соответствовать относительному расстоянию до границы зоны перехода. На другой стороне полоски fracl будет равно 1, a frac2 - соответствовать относительному расстоянию до границы зоны перехода. Следующая строчка кода (fracl = fracl* (1.0 - frac2)) выдает промежуточное значение для дальнейшего вычисления плавного перехода между BackColor и St ri peCol or. Но вообще-то неплохо было бы создать что-нибудь лучшее, чем простой плавный линейный переход. Следующая строчка кода выполняет интерполяцию Эрмита, так, как это делает функция smoothstep. Окончательное значение fracl в дальнейшем используется для перехода между BackCol or и St ri peCol or.


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