то, что я пытаюсь сделать, — это улучшить мой настоящий Ray Tracer для создания Distributed Ray Tracer. Я бродил по Интернету, и все, что я мог найти о его реализации, было просто короткие вещи вроде:
-Заменить один луч с распределением лучей
-Стрелять несколько лучей, распределенных по интервалу
-Стрелять несколько лучей через каждый пиксель и случайным образом менять каждый луч
Мой вопрос: что означает «распределение»? Как я могу варьировать распределение лучей, проходящих через пиксель? В моем обычном Ray Tracer я снимаю один луч на пиксель. Для «распределения» лучей я могу понять, что я должен снимать несколько лучей вместо одного. Но в то же время я снимаю луч через пиксель с координатами (x, y).
for (int x = 0; x < WINDOW_WIDTH; x++)
{
for (int y = 0; y < WINDOW_HEIGHT; y++)
{
Vec3<float> rayDir = camera->pixelToWorld(x, y) - camera->position;
}
}
Итак, как я могу «варьировать каждый луч случайным образом»? Благодарю.
Существует несколько способов распределенной трассировки лучей, которые можно использовать для:
(1) сглаживание
(2) эффекты глубины резкости
(3) эффекты размытия в движении
Для (1) идея состоит в том, чтобы просто запустить в каждом пикселе пучок лучей вместо одного луча. Каждый луч будет проходить через центр пикселя немного вздрогнул случайным образом dx и dy (dx и dy будут меньше, чем размер пикселя).
Для (2) это немного сложнее, но это примерно та же идея: каждый луч снимается как линия, которая начинается от наблюдателя и проходит через центр пикселя (возможно, дрожит, если вы делаете (1), но давайте теперь забудем об этом сейчас). На этот раз, это позиция наблюдателя, которую вы дрожите, вы будете немного дрожать в позиции наблюдателя в направлении, ортогональном к экрану. Опять же, усредняя вклад числа лучей в каждом пикселе, фон будет более «размытым», чем передний план, потому что луч будет больше отклоняться на заднем плане.
Для (3) это точно такая же идея, но на этот раз это положение движущихся объектов, которые колеблются.
Примечание: есть также (4): сложные материалы с глянцевыми эффектами (они должны понимать немного материала, понятие BRDF = Двунаправленная функция распределения отражения).
Есть много разных способов сделать это, и это в некоторой степени зависит от того, что вы работаете в своей текущей реализации ray tracer.
Мой подход заключается в том, чтобы разбить проблему на модель работы. Другими словами, вы создаете очередь заданий для обработки каждым из ваших работников, где работником может быть поток или отдельная машина.
Все рабочие узлы равны, это означает, что нет различий в типах заданий, которые они могут выполнять. Это позволяет вам добавлять столько рабочих узлов, сколько вы хотите (ПРИМЕЧАНИЕ: количество вы можете добавить до того, как вы начнете получать отрицательные результаты).
Еще одним преимуществом этого является то, что вы можете масштабировать в соответствии с вашими доступными ресурсами — может быть, для тестирования вы просто используете несколько потоков на вашем локальном компьютере, но когда вы будете готовы сделать «производственные» образы, вы можете использовать дополнительные машины. Кроме того, рендеринг с одним рабочим потоком должен работать в этой настройке.
Каждому рабочему узлу понадобится доступ к сцене, так что это первый кусок данных для отправки. Тогда они просто начинают вытягивать из очереди на работу. Важно отметить, что вы должны делать это безопасным образом — только один работник должен иметь право претендовать на работу.
while(active)
{
fetch next job from job queue
if no job is available
{
sleep(1)
continue
}
process job
}
То, что вам нужно решить, это то, что влечет за собой «работа». Это единственный луч? Является ли один луч и все его последующие отскоки? Это порция лучей? Это решение о балансировке нагрузки будет зависеть от вашего трассировщика лучей. Вероятно, одного луча недостаточно, но это хорошая отправная точка. На самом деле, вы, вероятно, должны начать с одного луча на пиксель и выполнять одну работу на луч. Это даст вам хорошую основу для начала, как только у вас все заработает.
Удачи!