Понадобятся нам и координаты источника освещения. Конечно, можно использовать обычные переменные OpenGL, но, чтобы продемонстрировать использование uniform-переменных, определим координаты источника освещения как такую переменную1: uniform vec3 LightPosition: Необходимо также определить количество света, рассеиваемого поверхностью, иколичество отражаемого света. Можно было бы определить uniform-переменные, чтобы задавать эти величины из приложения, но здесь они определяются как константы, просто чтобы продемонстрировать дополнительные возможности языка:

const float SpecularContribution =0.3;

const float DiffuseContribution = 1.0 - SpecularContribution; И наконец, нужно определить значения для передачи фрагментному шейдеру. Каждый вершинный шейдер должен вычислить однородные координаты вершины и сохранить их во встроенной переменной gl Position, и в данном шейдере тоже нужно это сделать. Шаблон кирпичей будет вычисляться во фрагментном шейдере «на лёту» как результат вычисления некоей функции с аргументами х ъу - геометрическими значениями координат в модельной системе, специально для этого объявлена varying-переменная MCposition. Чтобы применить эффект освещения к верхней части кирпича, некоторая часть вычислений для освещения будет выполняться во фрагментном шейдере. Но большая часть этих вычислений все же будет сделана в вершинном шейдере, который будет возвращать вычисленную силу света фрагментному шейдеру в varying-переменной Ligbtlntensity. Вот как определяются эти две varying-переменные:

varying float LightIntensity: varying vec2 MCposition; Теперь все готово для написания вершинного шейдера. Начнем с объявления точки входа для вершинного шейдера и вычисления координат вершины в пространстве обзора: void main(void)

{

vec3 ecPosition = vec3 (gl_ModelViewMatrix * gl_Vertex); В первой строке кода вершинного шейдера объявляется переменная ecPosition, в которую будут занесены вычисленные координаты вершины в пространстве обзора. Эти координаты вычисляются из значений gl_Vertex, преобразованных с помощью текущей.матрицы модели-вида gl_Model ViewMatrix. Так как один из операндов -7 матрица, а второй - вектор, оператор * выполняет математическое, а не покомпонентное умножение.

Результат умножения матрицы на вектор будет типа vec4, однако ecPosition объявлена как vec3. Так как в языке шейдеров OpenGL нет автоматического преобразования типов, его приходится выполнять явно с использованием конструктора. При этом четвертый компонент вектора отбрасывается и типы операндов оператора присваивания будут совместимыми. (Конструкторы, помимо прочего, выполняют еще и некоторые преобразования типов; более подробно об этом говорилось в разделе 3.3.) При дальнейших вычислениях координаты вершины в пространстве обзора будут использоваться для вычисления освещения.

Вычислить освещение в этом примере совсем не сложно. Какая-то часть света из источника будет рассеиваться (то есть отражаться во всех направлениях). В направлениях, близких к направлению отражения от источника освещения, будет наблюдаться зеркальное отражение. Чтобы вычислить рассеивание света, нужно определить угол между поступающим лучом света и нормалью поверхности. Чтобы вычислить отражение света, нужно определить угол между направлением отражения и направлением обзора. Сначала преобразуем нормаль: vec3 tnorm = normalize(gl__NormalMatrix * gl_Normal);


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