}

Полный код созданного вершинного шейдера приведен в листинге 6.1.

Листинг 6.1. Исходный код шейдера кирпичной стены

uniform vec3 LightPosition;

c®nst float SpecularContribution = 0.3:

const float DiffuseContribution = 1.0 - SpecularContribution:

varying float Ligh.tlntensity: varying vec2 MCposition:

void main(void)

(

vec3 ecPosition = vec3 (gl_Mode1ViewMatrix * gl_Vertex): vec3 tnorni = normal ize(gl_NormalMatrix * gl_Normal); vec3 lightVec - normalize(LightPosition - ecPosition): vec3 reflectVec = reflect С-lightVec. tnorm): vec3 viewVec = normalize(-ecPosition): float diffuse - max(dot(ligh.tVec. tnorm). 0.0): float spec =0.0:

If (diffuse >0.0)

{

spec - max(dot(reflectVec, viewVec), 0.0): spec = powtspec, 16.0);

}

Lightlntensity = DiffuseContribution * diffuse +

SpecularContribution * spec:

MCposition = gl_Vertex.xy; gl_Position = ftransformO:

]

6,3. Фрагментный шейдер

Назначение фрагментного шейдера - вычислять цвет для фрагмента, или значение глубины для него, или и то и другое. В данном случае (и на самом деле в большинстве фрагментных шейдеров) будет вычисляться только цвет фрагмента, а значение глубины уже вычислено на этапе растеризации OpenGL. Так что назначение данного шейдера - вычислить цвет текущего фрагмента.

Фрагментный шейдер кирпичной стены начинается с определения некоторых uniform-переменных, отличающихся от определенных в вершинном шейдере. Рисунок кирпичей был параметр из ирован именно для того, чтобы было легче изменять его. Эти параметры, являющиеся постоянными для конкретного примитива, задаются в uniform-переменных и инициализированы (а позже изменены) приложением. При этом в приложении будет легко сделать так, чтобы эти параметры задавал пользователь - например, ползунком или в окне выбора цвета. Данный фрагментный шейдер использует параметры, показанные на рис. 6.1. Они определены как uniform-переменные:

uniform vec3 BrickColor. MortarColor; uniform vec2 BrickSize; uniform vec2 BrickPct: Для того чтобы рисунок не смещался относительно объекта при движении, нужно «привязать» его к объекту. Начало фрагмента рисунка определяется в пространстве координат объекта, вычисляется вершинным шейдером и передается через varying-переменную MCposition: varying vec2 MCposition; Эта переменная вычисляется при обработке каждой вершины в вершинном шейдере, а потом интерполируется в пределах примитива и становится доступной фрагментному шейдеру во время работы с каждым фрагментом. Фрагментный шейдер использует это значение, чтобы определить, как положение фрагмента соотносится с рисунком из кирпичей. Еще одна входная varying-переменная объявлена так: varying float Lightlntensity; Эта переменная содержит интерполированное значение интенсивности освещения, которое вычисляется для каждой вершины в вершинном шейдере. Следует обратить внимание на то, что обе varying-переменные, определенные в этом фрагментном шейдере, определены с точно такими же типами, как соответствующие переменные в вершинном шейдере. Если типы не совпадают, происходит ошибка компоновки.

После определения всех необходимых uniform- и varying-переменных определяется код фрагментного шейдера: void main (void)


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