среда, июля 27, 2005

Строю карты теней

По просьбе Джима мне нужно было для нашей игрушки построить тени, которые темны, густы и зловещи. При этом в тени менгиров должны обязательно стонать проклятые души. Для этой непростой задачи я выбрала карты теней (shadowmaps). Почему именно их? Мне нужно смоделировать тени от удаленного источника света, лучи идут параллельно. Это я о солнце. При этом местность открытая. Идеальная ситуация для карт теней.
Алгоритм построения карт теней был предложен Лансом Виллиамсом (Lance Williams) в 1978 году. Его работа по этому поводу называлась "Наложение изогнутых теней на изогнутые поверхности" (Casting curved shadows on curved surfaces).

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

  1. Перемещаем камеру в положение источника света. Рендерим то, что отбрасывает тень.
  2. Потом возвращаем камеру обратно и рендерим сцену, накладывая на нее тень. Тень при этом придется хитрым образом преобразовать. Повернуть там, растянуть. В конце поста приведены ссылки где есть необходимые матрицы.
При наложении надо учитывать глубину, то бишь сравнивать Z координату со стороны источника света и со стороны камеры. Иначе тени будут отбрасываться совсем не туда, куда хотелось бы. Вон, глядите как она по склону вверх карабкается...

Это был вариант без учета глубины. Просто отрендерила в картинку и наложила поверх сцены.

Тень отрендеренная со стороны источника света

+ (накладывается на сцену)

= (получаем сцену с тенью)


Наложение с анализом глубины уберет лишнее:


Я пользуюсь возможностями карточек GeForce, которые позволяют делать текстуры глубины (DepthTextures). Создаю D3DUSAGE_DEPTHSTENCIL текстуру, ставлю ее в качестве Z-буфера, для изображения ставлю обычную текстуру. Цвет пишу серый, при этом объекты можно не текстурировать. Потом получившуюся текстуру накладываю, используя в качестве маски текстуру глубины. Вроде как ATI мне такое делать не позволит, надо будет проверить. Но на ATI можно использовать шейдеры. В любом случае, такое точно не пройдет на GeForce2 и на Intel 8XX, а я хотела, чтобы тени работали и на них.
В своих поисках я наткнулась на весьма экзотический метод построения карт теней с помощью буфера, изначально предназначенного для тумана. Можно попробовать, но фпс у автора метода весьма низкий получается.
Смотрела индексные карты теней, которые у меня заработали даже на Riva TNT2 Ultra, но у меня их использовать не получится, тень из вышеприведенного примера не построишь с их помощью.
Если кто делал тени на карточках класса GeForce2 и ниже, поделитесь опытом, плз.

Ссылки по теме:
Shadow Mapping Tutorial
Implementing Shadow Maps on Mainstream Graphics Hardware - Intel Software Network
Shadow Mapping and Shadow Volumes
Hardware Shadow Mapping - NVIDIA
Вариант от ATI через шейдеры

Technorati tag:

3 коммент.:

Анонимный комментирует...

Что-то подобное давно (еще в 2000) делала, но на Open GL.
Там с помощью glReadPixels( GL_DEPTH...) значения z переносились в буфер, вручную сравнивались (т.е. z сцены и z карты теней, полученной с камеры-источника света), а потом в результате в shadow-map текстуру глубина (значение z после сравнения) записывалось как альфа-компонент (GL_RGBA текстура). И там была возможность наложения текстуры в режиме сравнения альфы, и отсечения, если больше/меньше.
Я, правда, уже плохо помню конкретные детали, - только идея, что z-значения в альфа-компонент переносились. Может, в D3D тоже можно как-нибудь эту z руками в alpha компонент записать.
Если это может помочь, можно поискать старое, поточнее чтоб было.
// tensor

Anonymous комментирует...

А какие Вы сейчас используете технологии для создания теней в сцене? И, если можно, со ссылками :) А то тени на основе карт уже устаревшие...

Alena комментирует...

Anonymous

А какие Вы сейчас используете технологии для создания теней в сцене? И, если можно, со ссылками :) А то тени на основе карт уже устаревшие...

Сейчас никакие, вообще давно не занималась графикой.