1. Работа с освещением
Как в мире реальном человеческое зрение работает,
улавливая отраженные от объектов световые лучи, так и в мире виртуальном.
За одним отличием, если
не использовать свет, то все объекты в мире будут белые и плоские. Поэтому
сейчас нам нужно рассмотреть такую важную составляющую Leadwerks Engine , как освещение.
Вернемся к коду первого урока, внеся в него некоторые
изменения. Создавая куб, присвоим результат работы функции переменной cube имеющей тип TEntity.
//Создаем куб
TEntity cube = LE.CreateCube();
TEntity – переводится как сущность, и является базовым для большинства классов в
движке. Например, ранее мы создали так камеру. Теперь же мы можем
воздействовать на наш куб.
Внесем изменения в главный цикл, добавив функцию
вращения TurnEntity:
//Главный цикл
while (!LE.KeyHit(Keys.KEY_ESCAPE))
// пока не нажата ESCAPE
{
// Вращаем куб
LE.TurnEntity(cube,
LE.Vec3(0.5f));
//Обновляем мир
LE.UpdateWorld(1);
//Рисуем мир
LE.RenderWorld(LE.RENDER_ALL);
//Переключаем буфер
LE.Flip(1);
}
Запустив
измененный код мы увидим вращающийся куб, правда, на куб он не особо похож,
многогранник какой-то:
Отложенное освещение
Начиная с версии 2.1 Leadwerks Engine поддерживает технологию отложенного освещения (Deferred
Lighting). Эта технология позволяет
создавать потрясающие визуальные эфекты с множеством источников света, при этом
не так уж и сильно загружая оборудование. Достигается это благодаря тому, что
различные техники освещения просчитываются самостоятельно в отдельное
изображение, называемое буфером, а потом на основе нескольких изображений
создается финальное, которое и будет выведено на экран.
Сейчас мы создадим буфер, в который будет рисоваться
цвет, глубина и нормали. Добавляем перед главным циклом код:
//создаем буфер
TBuffer
buffer = LE.CreateBuffer(800, 600, LE.BUFFER_COLOR0 | LE.BUFFER_DEPTH
| LE.BUFFER_NORMAL);
Здесь функция CreateBuffer создает буфер указанного размера. Размер буфера
должен соответствовать размеру экрана.
Дальше создаем источник света. Источник бывает трех видов точечный,
зональный и направленный.
- Точечный свет (point light) — Этот источник представляет
из себя размещенную в пространстве точку, он испускает свет во всех
направлениях.
- Направленный свет (directional light) — этот
источник не имеет положения в пространстве, он испускает параллельные
световые лучи в заданном направлении.
- Зональный свет (spot light) — этот источник
света похож на фонарик; у него есть положения в пространстве и он
испускает конус лучей в заданном направлении.
Мы воспользуемся зональным:
//Создаем источник света
TEntity light = LE.CreateSpotLight();
//устанавливаем позицию
LE.PositionEntity(light,
LE.Vec3(2, 2, -2));
LE.RotateEntity(light,
LE.Vec3(45, 45, 0));
Теперь нам нужно выполнить определенную
последовательность действия.
1. Сделать созданный буфер активным.
2. Отрисовать в этот буфер все объекты
3. Деактивировать свой буфер, вернув предыдущий.
4. Провести расчет и отрисовку изображения на основе
своего буфера.
//Сделать созданный буфер активным.
LE.SetBuffer(buffer);
//Рисуем мир
LE.RenderWorld(LE.RENDER_ALL);
//Деактивировать свой буфер, вернув предыдущий
LE.SetBuffer(LE.BackBuffer());
//Провести расчет и отрисовку изображения на основе своего
буфера
LE.RenderLights(buffer);
Запустим код. Теперь, благодаря освещению, куб становится
похожим на объемный объект.
Но это еще не все. Освещенные объекты обычно
отбрасывают тень. Нужно добавить в сцену объект, на котором будет тень от
нашего куба.
//Создаем куб
TMesh
ground = LE.CreateCube();
//Меняем размеры и позицию
LE.ScaleMesh(ground, Vec3(10, 0.1, 10));
LE.PositionEntity(ground, Vec3(0, -2, 0));
Вот что мы увидим:
В процессе работы полезно видеть источники света и его
направление. Делается это с помощью функции:
//Визуализация источников света
LE.DebugLights(1);
Ну и весь код:
class Program
{
static void Main(string[]
args)
{
// подключение dll движка
LE.Initialize();
//Создание окна для вивода графики
LE.Graphics(640, 480, 0, 0, LE.GRAPHICS_BACKBUFFER + LE.GRAPHICS_DEPTHBUFFER);
//Создаем мир. Это делается в первую очередь.
LE.CreateWorld();
//Создаем камеру
TEntity cam = LE.CreateCamera();
// Устанавливаем координаты камеры
LE.MoveEntity(cam, LE.Vec3(0, 0, -5));
//Создаем куб
TEntity cube = LE.CreateCube();
//Создаем источник света
TEntity light = LE.CreateSpotLight();
//устанавливаем позицию
LE.PositionEntity(light,
LE.Vec3(2, 2, -2));
LE.RotateEntity(light,
LE.Vec3(45, 45, 0));
//создаем буфер
TBuffer
buffer = LE.CreateBuffer(800, 600, LE.BUFFER_COLOR0 | LE.BUFFER_DEPTH
| LE.BUFFER_NORMAL);
//Создаем куб
TMesh ground = LE.CreateCube();
//Меняем размеры и позицию
LE.ScaleMesh(ground, LE.Vec3(10, 0.1f, 10));
LE.PositionEntity(ground,
LE.Vec3(0, -2, 0));
//Визуализация источников света
LE.DebugLights(1);
//Главный цикл
while (!LE.KeyHit(Keys.KEY_ESCAPE)) //
пока не нажата ESCAPE
{
//Вращаем куб
LE.TurnEntity(cube, LE.Vec3(0.5f));
//Обновляем мир
LE.UpdateWorld(1);
//Сделать созданный буфер активным.
LE.SetBuffer(buffer);
//Рисуем мир
LE.RenderWorld(LE.RENDER_ALL);
//Деактивировать свой буфер, вернув предыдущий
LE.SetBuffer(LE.BackBuffer());
//Провести расчет и отрисовку изображения на
основе своего буфера
LE.RenderLights(buffer);
//Переключаем буфер
LE.Flip(1);
}
//Отключаем движок и выгружаем dll из памяти
LE.Terminate();
}
}
Код также можно скачать здесь.
|