Листинг 11.7. Вершинный шейдер для процедурного метода бугристой поверхности
varying vec3 LightDir; varying vec3 EyeDir;
uniform vec3 LightPosntion;
attribute vec3 Tangent;
void main(void)
g1_TexCoord[0] = glMultiTexCoordO:
vec3 n = norraalize(gl_NormalMatnx * gl_Normal): vec3 t = normalize(gl_NormalMatrix * Tangent); vec3 b = crossfn. t):
vec3 v:
v.x - doULightPosition, t); v.y = dotCLightPosition. b):
11.4.2. Вершинный шейдер
EyeDi r exposition
= vec3 CglJfodelViewMatrix * gl_Vertex); = ftransforme);
продолжение &
Процедурные текстурные шейдеры
Листинг 11.7 (продолжение)
v.z = dotdightPosition, п); LlghtDir = normalize(v);
v.x = dot(EyeDir. t); v.y = dotCEyeDir, b); v.z = dot(EyeDir. n): EyeDir - normalizeCv):
)
11.4.3. Фрагментный шейдер
Фрагментный шейдер для метода бугристой поверхности приведен в листинге 11.8. Через uniform-переменные передаются некоторые характеристики шаблона бугорков, а именно: BumpDensity (количество бугорков в заданной области) и Bump-Size (размеры бугорков). Также задаются характеристики самой поверхности: SurfaceColor (основной цвет поверхности) и SpecularFactor (свойство рассеянного отражения поверхности).
Вычисляемые бугорки будут круглыми. Так как для вычисления расположения бугорков используются текстурные координаты, сначала нужно умножить входные текстурные координаты на значение density - от этого зависит количество бугорков на поверхности. Получив некую сетку, вычисляем бугорок в каждой ее ячейке. Компоненты вектора р вычисляются как расстояние от центра бугорка в направлениях х и у. (Нам нужно всего лишь изменить нормаль в направлениях х и у. Значение z для преобразованной нормали всегда будет 1,0.) «Ложное расстояние» d вычисляется возведением в квадрат компонентов р и последующим их сложением. (Настоящее расстояние можно вычислить извлечением квадратного корня, но обычно это не требуется, если BumpSi ге является не абсолютным, а относительным значением.)
Чтобы правильно вычислить отражение позже, нужно предварительно нормализовать изменяющую нормаль. Эта нормаль должна быть единичным вектором, чтобы потом можно было выполнить операцию dot и получить точные значения косинуса для использования при вычислении освещения. Вектор нормализуется умножением каждого компонента нормали на l,0/sqrt(x2 + у2 + г1). При вычислении d часть необходимых данных уже получена (то есть х2 + у2). Так как z вообще не меняется, мы знаем, что z2 всегда будет 1,0. Чтобы уменьшить количество вычислений, коэффициент нормализации в данном случае будет вычисляться по формуле l,0/sqrt(d+ 1,0).