Листинг 15.1. Вершинный шейдер штриховки
uniform vec3 LightPosition: uniform float Time:
varying vec3 ObjPos: varying float V:
varying float Lightlntensity: void main(void)
{
ObjPos = (vec3 (gl_Vertex) + vec3 (0.0, 0.0. Time)) * 0.2;
vec3 pos = vec3 (gl_HodelViewMatrix * gl_Vertex); vec3 tnorm = normalize(gl_NormalMatrix * gl_Normal): vec3 lightVec - normali ze(Li ghtPosi ti on - pos):
Lightlntensity = max(dot(lightVec, tnorm), 0.0):
V = gl_MultiTexCoord0.t: // используйте ,s для вертикальных полос
gl_Position = ftransformO:
}
5.1.3. Рисование штриховых полосок
Рассматриваемый фрагментный шейдер должен определить цвет фрагмента - белый или черный - таким образом, чтобы получились линии на поверхности объекта. Здесь есть несколько особенностей. Покажем применение нескольких методов на простом объекте - сфере.
Начнем с такого же кода, который представлен в разделе 14.4.1 для вертикальных полосок, а именно:
float sawtooth = fract(V * 16.0);
float triangle = abs(2.0 * sawtooth - 1.0);
float square = step(0.5. triangle): Здесь V - varying-переменная, передаваемая из вершинного шейдера, она равна текстурной координате s при рисовании вертикальных штрихов и текстурной координате t при рисовании горизонтальных штрихов. Число 16 означает, что будут нарисованы 16 белых и 16 черных полосок. Результат выполнения этого кода показан на рис. 15.1. Относительный размер белых и черных полосок можно изменять с помощью изменения порогового значения функции step.
Рис. 15.1. Сфера с полосками, созданными процедурно с помощью текстурной координаты s1
15.1.4. Вычисление толщины штриха
Сейчас полоски выглядят довольно хорошо, но они не одинаковой ширины: широкие возле экватора и узкие возле полюса. Нужно, чтобы линии были приблизительно одинаковой ширины, а для этого понадобятся функции dFdx и dFdy: float dp = 1engthСvec2 (dFdx(V), dFdy(V)));
Рис. 15.2. Выравнивание частоты полосок: а - целая часть логарифма градиента используется для определения частоты полосок; б- сфера с высокой частотой полосок; в - целая часть логарифма используется для выравнивания частоты полосок; г- полоски с конусовидными окончаниями1
В результате получается значение градиента, то есть скорость изменения V в заданной точке поверхности (см. раздел 14.4.3). С помощью этого значения можно выровнять ширину линий. (Теперь приблизительное значение градиента, описанное в разделе 14.4.3, не годится, так как здесь вычисляется не ширина фильтра для сглаживания, а частота полосок. Значения должны быть инвариантны при вращении объекта. Поэтому нужно знать не сумму абсолютных значений двух компонентов вектора-градиента, а его реальную длину.) Логарифм (с основой 2) этого значения нужен для согласования ширины по шагам: каждый раз dp удваива ется, количество линий - тоже (результат показан на рис. 15.2, а). Линии получаются слишком тонкие или слишком жирные. Чтобы избежать этого (так как мы добиваемся постоянной ширины линий), нужно уменьшить количество линий при значительном увеличении их ширины. Это достигается отрицанием логарифма: