Тени в реальном времени

Xtreme3D

Урок 13
Тени в реальном времени

Уровень: средний
Версия Xtreme3D: 3.0.x
Автор урока: Gecko

Xtreme3D поддерживает несколько способов рендерить тени. Во-первых, тени (и освещение в целом) могут быть предрассчитаны и "запечены" в текстуру - такая техника называется картой освещения (Lightmapping). Она позволяет получить очень красивый и реалистичный результат, но получившиеся тени будут статичными. Соответственно, эта техника применима только к неподвижным объектам - например, к интерьерам и архитектуре. К тому же, далеко не все форматы 3D-моделей поддерживают карты освещения, и не во всех 3D-редакторах их можно создавать.

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

Также имеются две техники отрисовки объемных теней - shadow volume и shadow mapping. Первая заключается в создании объекта, определяющего объем, внутри которого точки находятся в тени. Данный метод дает очень точные тени на любом расстоянии, но работает достаточно медленно. Куда более перспективной выглядит новая техника, появившаяся в Xtreme3D 3.0 - теневые карты (shadow mapping). С их помощью можно очень быстро рендерить мягкие тени - но, правда, на ограниченном расстоянии от камеры.

Рассмотрим сначала теневую плоскость. Создать ее очень просто:

shadowTarget = DummycubeCreate(global.scene);
shadowPlane = ShadowplaneCreate(20, 20, 10, 10, shadowTarget, light, c_black, 0.5, global.scene);

Теперь остается только добавить те объекты, которые должны отбрасывать тень, в потомки к shadowTarget.

Работать с shadow volume ненамного сложнее:

sv = ShadowvolumeCreate(global.scene);
ShadowvolumeAddLight(sv, light);

Добавьте те объекты, на которые должна падать тень, в потомки к sv. Те объекты, которые должны отбрасывать тень, добавляются так:

ShadowvolumeAddOccluder(sv, obj);