Особенности моделирования света: Быстрый просчет теней


Вспомним, как наш мозг обрабатывает поступающие из глаза данные (глава Физика света). Только максимально приближенная имитация поведения света делает изображение наиболее понятным.

       

Вот, например, взгляните на изображение слева. Там изображены два шара. Один из них парит над зеленой поверхностью стола, второй лежит на поверхности. Но, глядя на это изображение, мы не можем сказать, какой из них касается стола, а какой нет. Более того, мы даже не можем определить положение этих шаров в пространстве и даже их размер. А теперь взгляните на картинку справа. Вот! Теперь нам все ясно. Красный шар больше синего и находится прямо на столе в удалении. Синий шар висит в воздухе и он гораздо ближе к нам. А эти две картинки отличаются лишь тем, что правая отображает тени от объектов, а левая нет.

Как вы можете видеть, тени снабжают наблюдателя огромным количеством информации о трехмерной сцене. Объект, отбрасывающий тень значительно более понятен. Тени придают глубину сцене и дают нам интуитивное представление о местоположении источников света. Взгляните на Quake. Его тени от источников света создают свою собственную игровую атмосферу, без которой мы просто не представим Quake. И представьте себе, насколько скучной станет сцена, если все будет иметь одинаковую яркость. (Для того, что бы это увидеть достаточно ввести в игровой консоли Quake команду "r_fullbright 1")

Простейший алгоритм просчета тени

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

Для каждого полигона сцены, создается другой полигон, который будет действовать как тень первого. Все вершины полигона тени будут находиться в пределах плоскости, на которую производится проекция. Алгоритм будет следующий:

Для каждой вершины: создать вектор от источника света до вершины. Удлинить вектор так, чтобы он коснулся поверхности. Сложить вектор с положением источника света, и мы получим точку, определяющую положение вершины полигона тени.

Давайте посмотрим на примере. Взгляните на изображение сверху. Полигон A, B, C отбрасывает тень от источника света L на плоскость и при этом формируется полигон Sa, Sb, Sc. Плоскость в нашем случае горизонтальна, т.е. параллельна плоскости осей XZ.

Начнем с вершины А и получим вершину Sa для тени.

Создадим вектор от источника света до вершины.

V = A — L

Удлиним вектор так, чтобы он коснулся нашей плоскости

V = V * ((y1+y2) / y1)

y1+y2 — это расстояние от источника света до плоскости. y2 — расстояние от точки А до плоскости. Так как плоскость горизонтальна и проходит через начало координат, то значения y1 и y2 легко определить. y2 — это Y координата вершины А и (y1+y2) — это Y координата точки L.

Сложим вектор с точкой источника света и получим точку вершины полигона тени.

Sa = L + V

Сделайте то же самое для двух других вершин В и С и получите Sb и Sc. А теперь, имея координаты вершин, отрисовать полигон обычным методом не представляет труда.

Просчет теней на произвольных поверхностях

Процедура аналогична предыдущей, только здесь несколько сложнее определить значения y1 и y2. Для начала вам нужно определить поверхность. Есть несколько методов, но в нашем случае мы рассмотрим метод, когда поверхность определяется одной точкой плоскости и вектором, исходящим из точки и перпендикулярным поверхности (нормалью).

Предположим, что вектор нормали это (Na, Nb, Nc), а координаты точки в пространстве — это (Px, Py, Pz). Нам надо определить расстояние (distance) от этой точки до вышеуказанной поверхности.

                 (Na*Px + Nb*Py + Nc*Pz)
Distance = ------------------------------------
                 sqrt(Na2 + Nb2 + Nc2)

(где sqrt — означает операцию извлечения квадратного корня)

В приведенной формуле мы считаем, что поверхность проходит через начало координат.

Важные замечания

Здесь есть несколько "подводных камней". Данный метод будет прорисовывать тень даже в том случае, если источник света находится между полигоном и поверхностью. Более того, даже в том случае, если источник света находится вообще по другую сторону поверхности.

Чтобы исключить подобные вещи, необходимо или отслеживать наступление указанных условий, или исключить их наступление вообще.

[ Читайте по этой теме: Рельефное текстурирование ]

[ Читайте по этой теме: Эффект "размытия" в движении ]



Материал для данной статьи любезно предоставил Hugo Elias




Дополнительно

Нашли ошибку на сайте? Выделите текст и нажмите Shift+Enter

Код для блога бета

Выделите HTML-код в поле, скопируйте его в буфер и вставьте в свой блог.