РАЗНОЕ
7.8. Обратная трассировка лучей
Обратная трассировка лучей (она же рэйкастинг, raycasting) - простой, хотя
и довольно медленный, метод получения высокореалистичных изображений. Этот
метод часто путают с прямой трассировкой лучей (рэйтрэйсинг, raytracing),
которая, на самом деле, практически никогда и никем не используется из-за
своей редкостной неэффективности. Впрочем, эти два термина уже практически
и не различают.
Итак, идея обратной трассировки лучей. Для определения цвета пиксела экрана
через него из камеры проводится луч, ищется его ближайшее пересечение со
сценой и определяется освещенность точки пересечения. Эта освещенность
складывается из отраженной и преломленной энергий, непосредственно
полученных от источников света, а также отраженной и преломленной энергий,
идущих от других объектов сцены. После определения освещенности этой точки
учитывается ослабление света при прохождении через прозрачный материал и
в результате получается цвет точки экрана.
Для определения освещенности, привносимой непосредственным освещением, из
точки пересечения выпускаются лучи ко всем источникам света и определяется
вклад всех источников, которые не заслонены другими объектами сцены. Для
определения отраженной и преломленной освещенности из точки выпускаются
отраженный и преломленный лучи и определяется привносимая ими освещенность.
Непосредственное освещение от источника света считаем, например, по уравнению
Фонга (см. п.5.1). На самом деле, компоненты diffuse и specular в этом
уравнении для большей реалистичности с точки зрения физики надо разделить
на квадрат расстояния до источника света, но обычно этим пренебрегают.
Ослабление света в прозрачной среде учитывается делением на коэффициент
k = exp(beta * l),
где
k | коэффициент ослабления |
beta | коэффициент прозрачности среды |
l | длина пути внутри среды |
Наконец, преломляется луч света по следующему закону:
sin(b) = n1 * sin(a) / n2,
где
a | угол между падающим лучом L и нормалью N |
b | угол между преломленным лучом L' и нормалью N |
n1 | коэффициент преломления среды, в которой проходит луч L |
n2 | коэффициент преломления среды, в которой проходит луч L' |
Вот иллюстрация.
Для воздуха считают beta = 0, n = 1; для всех остальных сред обычно beta > 0,
n > 1. Надо отметить, что все эти коэффициенты (отражения, преломления,
прозрачности) различны для каждой из трех цветовых компонент R, G, B. Еще
надо отметить, что обычно объекты непрозрачны и поэтому преломлением
пренебрегают.
Алгоритм работы функции трассировки луча с началом o = (ox,oy,oz) и
направлением d = (dx,dy,dz), возвращающей, кстати, освещенность по всем трем
цветовым компонентам, будет, таким образом, выглядеть примерно так:
ищем ближайшее пересечение луча со сценой (определяем точку p, где
произошло пересечение, выясняем, с каким конкретно объектом оно
произошло)
если не нашли, возвращаем 0
если пересечение есть, текущую освещенность полагаем равной
фоновой освещенности (ambient)
определяем вектор n, нормаль к объекту в точке пересечения
для кажого (точечного) источника света
считаем вектор l, соединяющий источник и точку p (начало в p)
ищем пересечение луча с началом в точке p и направлением d со сценой
считаем симметричный l относительно n вектор r
считаем по уравнению Фонга (оно использует n, l, r, d) освещенность
в точке за счет этого источника света, добавляем ее к текущей
считаем симметричный d относительно n вектор refl, то есть отраженный
вектор
трассируем отраженный луч (с началом p и направлением refl), добавляем
полученную освещенность к текущей
считаем направление преломленного луча (вектор refr) по d, n и
коэффициентам преломления
трассируем преломленный луч (с началом p и направлением refr), добавляем
полученную освещенность к текущей
покомпонентно умножаем текущую освещенность на цвет объекта
если для материала, заполняющего пройденную лучом от o до p трассу
beta != 0, умножаем текущую освещенность на коэффициент ослабления
возвращаем текущую освещенность
При стандартной камере, которая находится в (0,0,-dist), и ориентирована так,
что пикселу экрана (sx,sy) соотвествует 3D-точка (sx-xSize/2, ySize/2-sy, 0),
для получения цвета пиксела (sx,sy), очевидно, достаточно оттрассировать луч,
положив при этом
ox = oy = dz = 0,
oz = -dist,
dx = sx - xSize / 2,
dy = ySize / 2 - sy.