Рассказывает Фабиен Санглард, автор блога fabiensanglard.net
Недавно в интернете я наткнулся на трассировщик лучей на визитке Пола Гекберта. Для тех, кто не в курсе: это очень известная задача, изначально предложенная Полом Гекбертом 4-ого мая 1984 на comp.graphics. Ее суть в том, чтобы написать демонстрацию метода бросания лучей, которая бы… умещалась на визитной карточке (больше об этом читайте в разделе «Трассировка лучей» из книги «Графические драгоценности IV»)!
Версия Эндрю Кенслера — одна из самых потрясающих и красивых реализаций этой задачи, которые я видел. Из любопытства я решил разобраться в ней. В этой статье я напишу все, что смог понять сам.
Обратная сторона визитки
Вот так выглядит сам код:
Код выше выглядит… пугающе, но компилируется и запускается без проблем! Вы можете сохранить его на рабочем столе как card.cpp
, открыть консоль и ввести:
Через 27 секунд на экране появится следующее изображение:
Возможности визитки-трассировщика лучей
Возможности просто поражают!
— мир, состоящий из строго организованных сфер;
— текстурированный пол;
— небо с градиентом;
— мягкие тени;
— OMG, глубина резкости! Вы шутите?!
И все это на одной стороне визитной карточки! Посмотрим, как это работает.
Класс Vector
Рассмотрим первую часть кода:
Главная хитрость здесь — это сокращение ключевых слов типов int
и float
до i
и f
с помощью typedef
. Другой ход, с помощью которого можно можно уменьшить количество кода — это класс v
, используемый не только в качестве вектора, но и для обработки пикселей.
Вот код, приведенный выше, но отформатированный и с комментариями:
Rand() и данные для генерации мира
Следующий код также экономит много места с помощью объявления функции R
, которая возвращает случайное значение от 0 до 1 типа float. Это полезно при стохастическом сэмплировании, использующемся для blur-эффекта и мягких теней.
Массив G
содержит в себе закодированное целыми числами положение сфер в мире. Совокупность всех чисел — это битовый вектор из 9 строк и 19 столбцов.
Вот код, приведенный выше, но отформатированный и с комментариями:
Главный метод
Главный метод использует простой известный основанный на тексте формат изображений PPM. Изображение состоит из заголовка вида P6 [Ширина] [Высота] [Максимальное значение]
, за которым следует RGB-значение каждого пикселя.
Для каждого пикселя на изображении программа сэмплирует (S) цвет 64 лучей, аккумулирует результат и выводит его в stdout
.
Также этот код немного изменяет каждую координату начала луча и его направление. Это делается затем, чтобы создать эффект глубины резкости.
Вот код, приведенный выше, но отформатированный и с комментариями:
Сэмплер
Сэмплер S
— это функция, возвращающая цвет пикселя по данным координатам точки начала луча о
и его направлению d
. Если она натыкается на сферу, то она вызывает себя рекурсивно, а в ином случае (если луч не имеет препятствий на своем пути) в зависимости от направления возвращает либо цвет неба, либо цвет пола (базируясь на его клетчатой текстуре).
Обратите внимание на вызов функции R
при расчете направления света. Таким образом создается эффект «мягких теней».
Вот код, приведенный выше, но отформатированный и с комментариями:
Трэйсер
Функция T
(Tracer) отвечает за бросание луча из данной точки (o
) в данном направлении (d
). Она возвращает целое число, которое является кодом для результата бросания луча. 0
— луч ушел в небо, 1
— луч ушел в пол, 2
— луч наткнулся на сферу. Если была задета сфера, то функция обновляет переменные t
(параметр, используемый для вычисления дистанции пересения) и n
(полу-вектор при отскакивании от сферы).
Вот код, приведенный выше, но отформатированный и с комментариями:
Число Leet
Многие программисты пытались сократить код еще больше. Сам автор остановился на версии, предоставленной в этой статье. Знаете, почему?
Его размер — 1337 байт! Число Leet! Ха!
Материалы для ознакомления
Так как я провел очень много времени, читая про сам метод бросания лучей, вот несколько интересных ссылок и книг:
— scratchpixel.com — уроки по методу бросания лучей от профессионалов, работавших над «Историей игрушек», «Властелином колец», «Аватаром», «Гарри Поттером», «Пиратами Карибского моря» и многими другими фильмами;
— «Введение в метод бросания лучей» — довольно старая, но классическая книга;
— «Рендеринг, основанный на физике» — много математики, но все очень подробно и ясно объясняется.
Перевод статьи «Decyphering the business card racetracer»
Добавить комментарий