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

Глава 22. Тени.

I. ShadowPlane

ShadowPlane похож на обычный GLPlane. Особенностью ShadowPlane является то, что он поддерживает тени.

Создадим примитивное приложение, использующее ShadowPlane:

1. Создайте камеру, свойство Position.Z сделайте равным 10

2. Создайте GLSceneViewer, присвойте свойству Camera нашу камеру

3. Создайте инспектор объектов сцены (GLScene)

4. Создайте в сцене шарик (GLSphere)

5. Создайте источник света (LightSource)

В общем, всё как обычно.

6. Добавляем ShadowPlane, свойству ShadowLight присваиваем наш источник света (LightSource), свойству ShadowingObject присваиваем объект, который будет отбрасывать тень (GLSphere).

Всё! Запускаем и наслаждаемся тенями. Внизу расположена отлично иллюстрирующая картинка.

Если объектов, от которых должна идти тень, много, то свойству ShadowingObject следует представить DummyCube, предварительно поместив в него все объекты, от которых должна идти тень.

Неплохой пример можно посмотреть в стандартной папке demos по такому пути: …\Demos\specialsFX\shadowplane

II. GLShadowVolume

Тени можно строить при помощи стандартного компонента GLScene GLShadowVolume. Алгоритм этого компонента используется в “Doom 3” и в "Chronicles of Riddick". Тени выглядят достаточно хорошо, но требуют немало ресурсов. Компонент весьма заморочен, но разобраться можно! Создавать тени, используя GLShadowVolume, так:

1. Ставим в сцену объект GLShadowVolume. 2. Все, на что падает тень, вставляем в GLShadowVolume (то есть он должен быть родительским типом). 3. Создаём источник света и добавляем его в список GLShadowVolume1.Ligths. 4. Добавляем все объекты, которые отбрасывают тень, в список GLShadowVolume1.Occluders (во время выполнения так - GLShadowVolume1.Occluders.AddCaster(obj: TGLSceneBaseObject;)).

5.Не забывайте всегда присваивать GLSceneViewer1.Buffer.ContextOptions.roStencilBuffer:= True;

Совсем неплохие тени даёт компонент GLShadowVolume.

Пример можно посмотреть в стандартной папке demos по такому пути: Demos\specialsFX\shadowvolumes

III. GLZShadows

GLZShadows обеспечивает хорошие, но некудышно реализованные тени (подобные были в SplinterCell3). ZShadow рендерит в текстуру с положения источника света, потом эту текстуру накидывает на объекты.

А теперь сделаем пример с использованием GLZShadows

1. Кидаем на форму GLMemoryViewer (вкладка GLScene), в нем Width и Height это разрешение рендеримой текстуры (текстуры самой тени) 2. В сцену добавляем еще одну камеру, ставим в MemoryViewere (в свойство Camera) эту камеру.

3. Добавляем источник света (GLLightSource) 4. Добавляем объект GLPlane, открываем у него вкладку Material, затем вкладку Texture, выставляем Disabled=false, а TextureMode=tmModulate 5. Добавляем ZShadows; здесь свойство Viewer - вьювер, которым ты видишь сцену (при создании он называется GLSceneViewer1), и Caster - только что созданный MemoryViewer. 6. Теперь каждый раз, когда будет вызван метод GLZShadows.CastShadow, тени будут рендерится. Создайте каденсер и поместите это (GLZShadows.CastShadow) в его событие OnProgress.

Хороший пример можно скачать тут http://userlink.ru/glscene/download.php?view.103

Ещё один пример можно взять в стандартной демке по пути: Demos\specialsFX\shadows, но там демка прямо скажу “не ахти”.

Вот такие тени у меня получились.

IV. Lightmap

Lightmap (лайтмап, лайтмэп, в переводе с англ. — карта освещения) — метод освещения пространства в 3D-приложениях, заключающийся в том, что создается текстура, содержащая информацию об освещённости трехмерных моделей.

Этот метод значительно экономит ресурсы системы, так как не приходится рассчитывать падение света в режиме реального времени, но при этом проигрывает динамическому освещению в реалистичности.

Почти всегда карты освещения выравниваются с обычными текстурами полигонов, и каждый пиксель карты соответствует 4-32 текселам текстуры. Размеры карты определяются размерами минимального, ограничивающего полигон прямоугольника, стороны которого параллельны текстурным векторам. Этот метод применяется для создания всего статического освещения сцены. Освещение генерируется для статической геометрии до начала цикла рендеринга, и во время рендеринга в основном не изменяется. На современном оборудовании реализация полностью динамического освещения с использованием карт освещения невозможна из-за большой ресурсоемкости процесса создания лайтмэпов. Этот подход рассматривается как основа для большинства других алгоритмов рендеринга теней в реальном времени.

При создании карта заполняется черными пикселями. Далее, для каждого тексела карты освещения находятся трехмерные координаты точки на полигоне. Для этой точки необходимо построить список всех источников света, которые влияют на ее освещение: вектора из данной точки до источников света проверяются на пересечение с геометрией сцены, и если пересечение имеет место — то этот источник света не освещает точку (относительно него точка в тени). Остальные источники увеличивают значение тексела Lightmap на величину, зависящую от используемой модели освещения и положения источника света относительно точки. В целях улучшения внешнего вида картинки, к картам освещения часто применяется билинейная фильтрация. Эти операции повторяются для каждого освещаемого полигона сцены.

Во время рендеринга, карты освещения могут накладываться вторым проходом, с использованием альфа-блендинга. При наличии мультитекстурного оборудования можно накладывать текстуру и карту освещения за один проход.

Итак, как же это вложить в GLScene? Ответ прост. Начнём!

Для удачного запуска проекта необходимо создать в папке, из которой запускается проект, файл House.3DS. В нём придётся провести некоторую подготовительную работу. Я использовал 3DS max. Итак, нужно:

1. Создать модель.

2. Те полигоны, которые имеют различные материалы – поместить в отдельные объекты.

3. Расставить источники света.

4. Всем обьектам назначить материал.

5. С отдельных объектов нужно отрендить карты освещения. Выберите в меню Render\Render to texture (или кнопка “0”), в открывшейся форме выбираем линейку “Output ”, в ней кнопку “Add”, там выбираем Lightmap. Далее меняем настройки, если нужно, и жмём Render. Затем нужно расставить текстурные координаты. Для расстановки текстурных координат нужно для определённой области EditMesh/PolyMesh назначить “UVW Map”

6. Склейте все отделные объекты в один без изменения material ID (кнопка Attach).

7. Вернитесь к назначеным материалам, в закладке Self-Illumination присвойте карты освещения.

А теперь в Delphi:

1)Создадим:

GLSceneViewer

GLScene и здесь создадим объект GLFreeForm, назовём его map (наша карта для хранения объектов), свойство UseMeshMaterials присвоим true.

Создадим, соответственно, GLCamera, присвоив свойству Position.Z:=5; Position.X:=5; Position.Y:=5;

Поместим на форму GLMaterialLibrary, назовём её Materials и будем грузить сюда материалы, от которых должна идти тень.

Теперь поместим ещё одну GLMaterialLibrary, назовём её LightMaps и будем грузить сюда текстуру с тенью, саму LightMap.

И на последок бросьте на форму GLCadencer.

Теперь создаём в LightMaps материал. Потом запишите в событии FormCreate следующий код:

procedure TForm1.FormCreate(Sender: TObject);

begin

Materials.TexturePaths:=ExtractFilePath(Paramstr(0));

LightMaps.TexturePaths:=ExtractFilePath(Paramstr(0));

Map.MaterialLibrary:=Materials; //Присваиваем GLFreeForm’ у материал

Map.LightmapLibrary:=LightMaps; //Присваиваем GLFreeForm’ у материал (карту теней, LightMap)

Map.LoadFromFile('House.3DS');

with Materials.Materials.FindItemID(2)do begin

TextureScale.scale(15); //Растягиваем текстуру

Material.Texture.TextureMode:=tmDecal;

end;

with Materials.Materials.FindItemID(1)do begin

TextureScale.scale(6); //Растягиваем текстуру

Material.Texture.TextureMode:=tmDecal;

end;

with Materials.Materials.FindItemID(0)do begin

TextureScale.scale(2); //Растягиваем текстуру

Material.Texture.TextureMode:=tmDecal;

end;

Map.Scale.Scale(0.02); //Растягиваем текстуру

END;

Всё! Можете запустить и посмотреть, что получилось!

А готовый пример можно взять отсюда: http://www.glscene.ru/download.php?view.165