1. Постановка
задачи.
Дана простая сцена, состоящая из комнаты, двух параллелепипедов и одного прямоугольного площадного источника света: Необходимо написать программу,
которая:
1. Производит трассировку
лучей методом Монте-Карло, запоминая информацию об ударах фотонов в поверхности
сцены в фотонной карте. Трассировка и накапливание информации в фотонных
картах должно происходить в течение некоторого (задаваемого снаружи) промежутка
времени. Можно реализовать прерывание счета с клавиатуры.
2. Преобразует фотонные карты
в текстуры, наклеивает их на поверхности сцены и показывает результат используя
средства OpenGL. Ракурс картинки должен приблизительно соответствовать
представленному выше. Источник света должен быть представлен на изображении
в виде прямоугольника.
Ниже представлено краткое описание метода, предлагаемого для реализации и ссылки на полезную литературу. Луч (или фотон) в методе Монте-Карло обычно имеет следующие параметры: - направление полета; - энергию; - цвет.
Вообще говоря, цвет и энергия
имеют много общего. Например цвет можно выражать в некоторых физических
единицах. В этом случае, он будет нести в себе информацию и об энергии
фотона. Мы для простоты будем рассматривать следующие две модели фотона
(выбор за Вами):
1. Энергия луча всегда равна одной единице; Цвет фотона представляет из себя три числа с плавающей точкой, сумма которых всегда равна 1.0 (rr + rg + rb = 1.0). 2. Энергия фотона всегда равна одной единице; Цвет фотона всегда или красный,
или зеленый, или синий и равен 1.0.
Легко видеть, что первый подход более общий. Он также дает преимущество в скорости по сравнению со вторым. Второй же подход более прост в программировании - взаимодействие одноцветного луча с поверхностью описывается немного легче. Все поверхности в предлагаемой задаче прямоугольные и диффузные. Их единственным параметром является цвет. Если цветовые компоненты луча должны давать в сумме 1.0, то цвет поверхности необходимо представлять так, чтобы каждая компонента принадлежела интервалу [0,1]. При этом в цвете поверхности необходимо учитывать диффузную компоненту отражения kd. Так, например, для поверхности с цветом (255, 100, 0) и kd = 1.0, ее 'физический' цвет будет равен (1.0, 0.392, 0). Если же kd = 0.5, то 'физический' цвет будет равен (0.5, 0.196, 0.0). Фотонная карта предназначена
для того, чтобы запоминать информацию о падающих на поверхность фотонах.
С каждой поверхностью небходимо связать линейный массив, в который должны
записываться координаты точки (двухмерные, в пространстве поверхности)
и цвет попавшего в поверхность фотона. Этот массив и называется фотонной
картой.
3. Испускание луча из источника света. Цвет присваивается в зависимости от выбранного представления луча. 1. Если ваши лучи трехцветные (r,g,b), то цвет порожденного луча должен быть равен цвету источника света (с учетом нормализации к единице). 2. Если ваши лучи одноцветные, то надо выбирать цвет с помощью датчика равномерного распределения исходя из цвета источника (который предварительно необходимо нормализовать к единице). Например, пусть нормализованный цвет источника = (0.3, 0.59, 0.11). Тогда цвет луча выбирается следующим образом: a = rnd(0, 1); if (a <= 0.3) ray is red; else if (a <= 0.59) ray is green; else ray is blue;
Где rnd(a, b) - датчик равномерного распределения на отрезке [a, b]. 3.2 Выбор точки испускания луча. Задача выбора точки испускания луча в случае одного плоского площадного источника света, как в данном примере не представляет особых сложностей. Так как необходимо получить равномерную светимость по всей площади источника, можно использовать датчик равномерного распределения. Иначе говоря, координаты точки испускания могут быть найдены как: x = rnd(0, dx); y = rnd(0, dy); где (dx, dy) - линейные размеры прямоугольного источника света . 3.3 Выбор направления полета луча. Направление полета луча обычно находится в полярной системе координат (phi, theta). Угол phi выбырается с помощью датчика равномерного распределения rnd(-Pi, Pi). Для нахождения угла theta датчик равномерного распределения в явном виде не подходит, для источника, равномерно излучающено в одну полуплоскость плотность вероятности должна равняться sin(theta). Такой датчик распределения можно смоделировать с помощью датчика равномерного распределения следующим образом: a = 0.0; b = 1.0; while(b > sin(a)) { a = rnd(0, Pi/2.0); b = rnd(0, 1.0); } theta = a;
Угол theta отсчитывается
от нормали к поверхности.
4.
Взаимодействие луча с диффузной поверхностью.
При взаимодействие луча с диффузной поверхностью необходимо решить, трассировать луч дальше, либо уничтожить его и испустить новый луч из источника света. Решение должно быть основано на физических свойствах луча и поверхности. Так, например при столкновении абсолютно красного луча (1.0, 0.0, 0.0) с абсолютно зеленой поверхностью (0.0, 1.0, 0.0), луч будет поглащен с вероятностью 1.0 (зеленая поверхность отражает только зеленые лучи - этим и объясняется ее зеленый цвет). При попадании же на такую поверхность абсолютно зеленого луча, он будет отражен с вероятностью 1.0. Рассмотрим алгоритм нахождения
вероятности отражения луча от поверхности для типов представления лучей,
описанных в 1.
1. Трехцветные лучи. Пусть луч имеет цвет (rr, rg,
rb), а поверхность имеет цвет (sr, sg, sb). Тогда:
// найти вероятность отражения луча от поверхности p = rr * sr + rg * sg + rb * sb; if (rnd(0, 1) > p) луч поглощается; else { луч отражается; вычисляем новый цвет луча: rr *= sr; rg *= sg; rb *= sb; if (луч имеет нулевой (или почти нулевой) цвет) луч поглощается; else нормализовать цвет луча к 1.0; } 2. Одноцветные лучи являются
частным случаем многоцветных. Вам предлагается самим упростить алгоритм,
представленный выше, выбросив ненужные операции.
Далее, если луч был отражен
от поверхности, необходимо выбрать новое направление его полета. Для Ламбертовских
поверхностей, представленных в этом задании это делается в точности также,
как описано в пункте 3.3.
После окончания трассировки лучей методом Монте-Карло необходимо преобразовать фотонную карту в текстуру с заданным разрешением и наклеить эту текстуру на поверхность для генерации изображения с помощью OpenGL. Тектстура должна создаваться приблизительно так: for (x = 0; x < xres; ++x) for(y = 0; y < yres; ++y) texture[x, y] = photon_map.get_color((x - 1) / xres, (y - 1) / yres); где xres, yres - разрешение
текстуры, а фотоны в фотонной карте имеют координаты, принадлежащие отрезку
[0, 1].
функция get_color() работает приблизительно следующим образом: get_color(x, y) { найти все фотоны, лежещие в окружности с центром в точке (x, y) и некоторым радиусом (радиус выбирается на Ваше усмотрение); // вычислить освещенность данной точки illum = (сумма цветов фотонов * яркость источника света) / (общее количество фотонов * площать окружности); // перевести освещенность в светимоть // верно только для Ламбертовский поверхностей lum = illum / Pi; // конвертировать физическую lum в экранный цвет color = lum2rgb(lum); return color; }
Более полную информацию о методах хранения и доступа к фотонным картам можно найти здесь: Henrik Wann Jensen "A Practical Guide to Global Illumination using Photon Maps", Siggraph 1999, Course 7, Sunday,
August 8, 1999 ( PDF 5MB )
Перевод физической светимости
в экранный цвет должен производится так, чтобы была достигнута приемлемая
контрастность. При этом параметр maxlum (см. ниже) может задаваться как
параметр программы или быль задан жестко в коде.
lum2rgb(lum)
{
if (lum.r > maxlum)
lum.r = maxlum; if (lum.g > maxlum) lum.g = maxlum; if (lum.b > maxlum) lum.b = maxlum;
// нижеприведенная конвертация не учитывает гамма коррекцию монитора // ее учет даст Вам дополнительные баллы color.r = lum.r / maxlum * 255; color.g = lum.g / maxlum * 255; color.b = lum.b / maxlum * 255; }
1. Henrik Wann Jensen "A Practical Guide to Global Illumination using Photon Maps", Siggraph 1999, Course 7, Sunday,
August 8, 1999 ( PDF 5MB )
2. James Arvo "Backward Ray
Tracing" SIGGRAPH'86 Course Notes, 1986 ( ZIP
123 KB )
3. Rzhavin
|
Hosted by Graphics & Media Lab
http://graphics.cs.msu.su |
![]() |
mailto: Laboratory |