Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Учебник по GLScene.doc
Скачиваний:
255
Добавлен:
16.12.2018
Размер:
7.18 Mб
Скачать

Глава 43. Шейдеры glsl. Использование через компонент glslShader. Часть вторая – знакомимся со светом. Передача параметров в шейдер.

Карпенюк Алексей,

karpenyuk@bk.ru

(публикация стилизованная)

В предыдущей главе нам удалось создать и запустить простейший шейдер, который пока только равномерно закрашивал наш объект, из-за чего наш объект выглядел полностью плоским, в этом части мы с вами вернем ему объем.

Модели освещения (и не только) хорошо рассмотрены, к примеру, тут: http://bimedev.ru/post/2008/05/RenderMonkey.aspx. Рекомендую также ознакомиться с данной программой, так как разработка шейдера в среде Delphi достаточно сложное занятие.

Так как цель статьи научить использовать шейдеры в среде GLScene то я не стану особо задерживаться на вопросе написания самого шейдера. Вместо этого я рассмотрю вопрос передачи в шейдер из нашей программы различных параметров.

Итак, для начала возьмем модель диффузного освещения (описание взято с предыдущей ссылки):

Эта модель дает очень неплохой результат, так как интенсивность освещения каждой точки модели рассчитывается в зависимости от направления нормали поверхности и позиции источника света. В результате мы получаем неплохое затенение объекта. Общая формула этой модели выглядит так:

Idiffuse=Kd×Id×dot(N, L)

Idiffuse - степень освещенности для каждого пикселя

Kd - цвет материала

Id - интенсивность освещения

N - вектор нормали поверхности

L - положение источника освещения

dot - скалярное произведение (dot product) двух векторов.

Так же из этой же статьи были целиком взяты вершинный и фрагментный шейдер:

//Вершинный:

varying vec3 Normal; void main(void){

gl_Position = ftransform(); Normal = gl_Normal;

}

//Фрагментный:

varying vec3 Normal; uniform vec4 vec_light; uniform vec4 ambient_color;

uniform float ambient_intensity;

void main(void){

gl_FragColor = ambient_color * ambient_intensity * dot(Normal, vec_light);

}

Поместите их в соответствующие файлы, заменив предыдущий текст.

Итак, судя из описания, нам для работы этого шейдера потребуются несколько параметров, а именно – координаты источника освещения (vec_light), интенсивность освещения (ambient_intensity) и цвет материала (ambient_color), все остальное нам предоставит вершинный шейдер.

Итак, открываем наш старый проект. Прежде чем применить шейдер к материалу, компонент TGLSLShader вызывает событие onApply, вот оно нам и нужно:

Теперь нам нужно написать сам текст обработчика, для этого мы вернемся в наш шейдер и перепишем указанные ранее переменные из фрагментного шейдера (они там указаны как uniform) – vec_light, ambient_color и ambient_intensity.

Тут очень важно записать их правильно, так как шейдер чувствителен к регистру букв. Записали? Тогда

возвращаемся в программу. А именно – в обработчик событий onApply и пишем там такой

вот код:

procedure TForm1.GLSLShader1Apply(Shader: TGLCustomGLSLShader);

begin

with Shader do begin

Param['vec_light'].AsVector4f := VectorMake(1, 1, 1, 1);

Param['ambient_color'].AsVector4f := VectorMake(0.2, 0.2, 0.2, 1);

Param['ambient_intensity'].AsVector1f := 1;

end;

end;

Итак, как вы уже наверное догадались – тип данных uniform служит для связи шейдера с внешним миром, в нашем случае с нашей программой. Передать какое-то значение шейдеру можно воспользовавшись свойством:

Shader. Param[<имя параметра>].As<тип параметра>:=<значение параметра>;

При передаче параметров нужно следить за тем, чтоб совпадали имена и типы.

В нашем случае координаты источника света и цвет нашего объекта имеют в шейдере тип

vec4, что соответствует преобразованию типа в Delphi - AsVector4f. Параметр

ambient_intensity у нас задан как float, для передачи значения такому параметру необходимо сделать приведение типа как AsVector1f или же AsFloat.

Не забываем подключить к проекту модуль VectorGeometry, если хотите воспользоваться

такими функциями как VectorMake.

В нашем примере мы указали что интенсивность освещения у нас 1 (100%), цвет объекта у нас 20% серый, а источник освещения мы разместили в точке с координатами (1,1,1).

Итак – шейдер у нас уже написан, обработчик onApply мы уже тоже закончили, параметры задали – самое время запускать нашу программу:

Как видите, теперь наш объект освещен и «проявилась» его

трехмерность. Для закрепления можете поиграться различнми параметрами цвета и света.