distance[0] - dot(p, HalfSpaceO); distanced] = dot (p. HalfSpacel); distance[2] = dot(p. HalfSpace2): distance[3] = dotCp. Ha1fSpace3):

distance = smoothstep(-FWidth. FWidth. distance):

inorout +- dottdistance. vec4(1.0));

distance.^ = dotCp. HalfSpace4);

distance.у = StripeWidth - abs(p.z);

distance = smoothstep(-FWidth. FWidth. distance):

inorout -+= distance.x;

inorout - clamp(inorout, 0.0, 1.0):

surfColor = mix(Yellow, Red. inorout); Листинг 11.5 (продолжение)

surfColor = miх(surfColor. Blue, distance.у):

// norraal - точка на поверхности сферы (0.0.0) normal = р;

// Вычисление рассеянного освещения для каждого фрагмента intensity = 0.2; // ambient

intensity += 0.8 * clamp(dot(LightDir, normal}., 0.0, 1.0); surfColor *= intensity;

// Вычисления отраженнего освещения для каждого фрагмента intensity - clarapCdotCHVector, normal). 0.0. 1.0); intensity = pow(intensity. SpecularColor.a): surfColor += SpecilarColor * intensity:

gl_FragColor “ vec4 (surfColor. 1.0);

}

11.3. Сетка

Рассмотрим своего рода хитрость. Здесь будет показано, как не рисовать объект процедурно, В этом примере читатель увидит, как можно использовать команду di scard во фрагментном шейдере, чтобы получить интересные эффекты. Команда discard означает, что фрагмент будет отброшен и не попадет в буфер кадров вообще. Используем этот прием для рисования геометрических фигур с «дырками». Вершинный шейдер будет таким же, как вершинный шейдер полосок (см, раздел 11.1.1). Фрагментный шейдер приведен в листинге 11.6.

Листинг 11.6. Фрагментный шейдер для процедурного отбрасывания частей объекта

varying vee3 DIffuseColor: varying vec3 SpecularColor:

uniform vec2 Scale; uniform vec2 Threshold; uniform vec3 SurfaceColor:

void main (void)

{

float ss = fract(gl_TexCoord[0].s * Scale.s); float tt = fract(gl_TexCoard[0].t * Scale.t);

if ((ss > Threshold.s) && (tt > Threshold.t)) discard;

vec3 finalColor = SurfaceColor * DiffuseColor + SpecularColor; gl_FragColor = vec4 (finalColor, 1.0):

}

Отбрасываемая часть объекта определяется значениями 5 и t текстурных координат. Коэффициент масштаба применяется для того, чтобы определить частоту сетки. Затем вычисляется дробная часть отмасштабированного значения текетурных координат, чтобы в итоге получилось значение, принадлежащее диапазону [0,1]. Значения sh£ сравниваются с.заданным граничным значением. Если оба значения превышают граничное, фрагмент отбрасывается. В противном слу-яае вычисляется освещение и выполняется рендеринг фрагмента.

На цветном рис. 15 оба граничных значения были установлены в 0,13. Это означает, что больше чем три четверти фрагментов было отброшено! Получилась здырявая корова1».

1.4. Бугристая поверхность

Читатель уже видел процедурные шейдеры, которые меняют цвет (кирпичная стенка, полоски) и непрозрачность (сетка). Еще один интересный эффект можно получить, используя метод бугристой поверхности. Этот метод подразумевает изменение нормали поверхности перед наложением освещения. Изменение нормали может быть сделано алгоритмически, если накладывается какой-либо повторяющийся шаблон; можно просто добавлять шум к компонентам нормали, а можно брать значения из текстурной карты. Метод бугристой поверхности - эффективный способ сделать изображение более реалистичным, не увеличивая сложность геометрических фигур. Этот метод можно использовать для имитации деталей поверхности или ее неровностей.


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