- •Учебник
- •Оглавление
- •Введение
- •Глава 1
- •I. Установка
- •II. Удаление
- •Глава 2. Первый проект
- •Глава 3. Создание сцены в режиме design time
- •Создание объектов:
- •Глава 4. Примитивные объекты. Вкладка Basic geometry.
- •Глава 5. Ориентация, координаты.
- •Глава 6. Движение.
- •Глава 7. Как узнать, сколько сейчас fps?
- •Глава 8. Полноэкранный режим.
- •Глава 9. Работа с материалами.
- •I. Прямое обращение к .Material
- •Глава 10. Использование 3d моделей.
- •I. Форматы моделей
- •Глава 11. Прокси объекты.
- •Глава 12. Создание земной поверхности с glTerrainRenderer.
- •Глава 13. Создание земной поверхности с glFreeForm.
- •Глава 14. Итоги работы с glTerainrender и glFreeForm.
- •Глава 15. Создание земной поверхности с glHeightField.
- •Глава 15. Создание неба.
- •Глава 16. GlAtmosphere.
- •Глава 17. Спецэффекты.
- •I. Огонь
- •II. Молния
- •III. Дождь
- •IV. Снег
- •VI. Блики от источников света
- •Глава 18. Растительность.
- •I. Деревья и кустарники
- •II. Трава
- •Глава 19. Работа со шрифтами и вывод надписей.
- •I. Вывод текста через компонент glWindowsBitmapFont
- •II. Проблема с glWindowsBitmapFont в Windows Vista
- •Глава 20. Выделение объекта мышкой.
- •Глава 21. Создание сцены в режиме runtime.
- •Глава 22. Тени.
- •Глава 23. Туман.
- •Глава 24. Vbo или расширение arb_vertex_buffer_object в OpenGl.
- •Глава 25. Fbo или расширение ext_framebuffer_object в OpenGl.
- •Глава 26. Рисование на канве.
- •Глава 27. Использование чистого OpenGl.
- •Глава 28. Звуки.
- •I. Проигрывание звуков с помощью bass
- •II. Проигрывание звуков с помощью fmod
- •III. Проигрывание звуков с помощью OpenAl
- •Глава 29. Игровое меню.
- •Глава 30. Примитивная физика dce.
- •Глава 31. Физика ode.
- •II. Основы библиотеки ode(: tglodeManager и tglodeJointList) на примере создания подобия боулинга.
- •Глава 32. Физика Newton.
- •Глава 33. Ручная проверка коллизий.
- •V. Ручная проверка коллизии
- •Глава 34. Шейдеры. Терменология.
- •Глава 35. Шейдеры. История и компоненты.
- •Глава 36. Шейдеры glsl. Введение.
- •Глава 37. Шейдеры glsl. Использование без компонентов. Самый примитивный шейдер.
- •Глава 38. Шейдеры glsl. Немного о спецификации. Типы данных и переменные
- •Стандартные функции
- •Поддерживаемые компоненты векторов
- •Глава 40. Шейдеры glsl. Текстурирование.
- •Глава 41. Шейдеры glsl. Использование без компонентов. Мультитекстурирование. Смешение трёх цветов по базовой карте.
- •Глава 42. Шейдеры glsl. Использование через компонент glslShader. Часть первая – Первые шаги.
- •Глава 43. Шейдеры glsl. Использование через компонент glslShader. Часть вторая – знакомимся со светом. Передача параметров в шейдер.
- •Глава 44. Шейдеры glsl. Использование через компонент glslShader. Часть третья – текстуры.
- •Глава 45. RenderMonkey.
- •Глава 46. Оптимизация программы.
- •Глава 47. Практика. Создание мира
- •Приложение
- •I. Типы векторов и матриц
- •II. Работа с векторами
- •III. Работа с матрицами
- •IV. Методы объектов glScene
- •Предметный указатель по компонентам glScene
Глава 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 мы уже тоже закончили, параметры задали – самое время запускать нашу программу:
Как видите, теперь наш объект освещен и «проявилась» его
трехмерность. Для закрепления можете поиграться различнми параметрами цвета и света.