Листинг 11.8. Фрагментный шейдер для процедурного метода бугристой поверхности
varying vec3 LightDir; varying vec3 EyeDir:
uniform vec3 SurfaceColor; // = CO.7, 0.6. 0.18)
uniform float BumpDensity; // = 16.0
uniform float BumpSize; // = 0.15
uniform float SpecularFactor; // = 0,5
void main (void)
{
есЗ 1itColor; ec2 с = BumpDensity * gl_TexCoord[0],st; ec2 p - fract(c) ■ vec2 (0.5);
loat d. f:
= p.x * p.x + p.у * p.у:
=1.0 / sqrttd + 1.0);
f (d >= BumpSize)
{ p = vec2(0.0): f = 1.0; }
vec3 normDelta - vec3 (p.x, p.y, 1.0) * f;
litColor = SurfaceColor * max(dot(normDelta, LightDir), 0.0);
vec3 reflectDir = reflect (LightDir. normDelta);
float spec = max(dot(EyeDir. reflectDir), 0.0);
spec = pow(spe.c, 6.0.)
spec *=- SpecularFactor;
litColor = minditColor + spec, vec3 (1.0));
glFragColor = vec4 (litColor, 1.0);
}
Результаты применения такого шейдера к двум объектам, простому блоку и тору, показаны на цветном рис. 18. Текстурные координаты используются для определения расположения бугорков, и, так как текстурные координаты изменяются от 0,0 до 1,0 четыре раза по окружности тора, бугорки выглядят на этом объекте расположенными гораздо ближе друг к другу.
11.4.4. Карты нормали
Рассматриваемый шейдер можно легко изменить, чтобы он получал значения для изменения нормали нз текстуры, а не вычислял их самостоятельно. Текстура, которая содержит значения изменяемой нормали, называется карта нормали.
Пример карты нормали и результаты ее применения на простом блоке показаны на цветном рис. 19. Отдельные компоненты нормалей могут располагаться в диапазоне [-1, 1 ]. Карта нормали изображена синим цветом, так как вектор изменений до умолчанию (0, 0, 1) занесен в карту нормали как (0,5, 0,5, 1,0). Поддержка текстур со значениями с плавающей запятой, с 16 битами на каждый компонент появляется все в большем количестве графических акселераторов, но еще не считается используемой повсеместно. Если для хранения нормали выбран формат текстуры с плавающей запятой, это улучшает качество изображения (например, снижает «полосатость» при отражении освещения). Но при этом производительность может пострадать, так как здесь используется 16 бит на компонент вместо 8.
Вершинный шейдер будет таким же, как описанный в разделе 11.4.2, Фрагмен-тный шейдер - почти таким лее, как описанный ранее, за исключением того, что изменяющая нормаль не вычисляется, а считывается из карты нормали, находящейся в текстурной памяти,
11.5. Итоги
Искусный фокусник может создать иллюзию того, как из простого воздуха получается нечто. С помощью процедурных текстур вы как создатель шейдера можете превращать простые серые поверхности в цветные, узорчатые, бугристые или зеркальные. Все, что для этого нужно, - лишь придумать алгоритм, описывающий свойства воображаемой текстуры. Закодировав этот алгоритм как OpenGL-шсй-дер, вы тоже можете создать нечто из воздуха.