Трассировка лучей в Vulkan 1.2
Начиная с версии 1.2.162, кроссплатформенный графический API Vulkan получил встроенную поддержку трассировки лучей на GPU (расширение GL_EXT_ray_tracing) - недавно консорциум Khronos Group анонсировал соответствующий SDK. Эта технология была представлена компанией NVIDIA еще в 2018 году, что стало переломным событием в истории игровой графики: наконец-то трассировка доступна не только в рендер-движках, но и в играх!
Основным методом рендеринга в играх сегодня является растеризация - отрисовка двумерных треугольников с интерполяцией вершинных атрибутов. Преимуществом растеризации всегда была простота и вычислительная дешевизна, что позволило в конце 1990-х годов перенести ее на видеоускорители. Однако возможности ее сильно ограничены, поскольку программируемый конвейер растеризации предполагает локальность данных: вершинный шейдер обрабатывает только одну вершину, пиксельный шейдер - только один пиксель. Точная реализация многих оптических феноменов требует полной информации об окружении: это, например, тени, отражения, преломления, глобальное освещение и т.д. Их невозможно рассчитать "честно" без доступа ко всей сцене целиком. Трассировка лучей решает эту проблему, поскольку в ней информация о сцене всегда доступна полностью, однако видеокарты и графические API до сих пор не предоставляли встроенных средств для трассировки лучей. В последние годы стали появляться гибридные графические движки, объединяющие растеризацию с некоторыми элементами трассировки - например, для рендеринга тех же отражений. Обычно в таких случаях применяются упрощенные алгоритмы трассировки в экранном пространстве (screen space), легко реализуемые в рамках традиционного графического конвейера, но не являющиеся "честными".
Появление RTX от NVIDIA (а вскоре и аналогичной технологии в видеокартах семейства Radeon 6000 от AMD), фактически, сместило всю "координатную систему" современного рендеринга: становится возможным полный отказ от растеризации в пользу трассировки. Для использования RTX в приложениях NVIDIA изначально предложила API OptiX, затем появился DXR в DirectX, однако унифицированного кроссплатформенного решения долгое время не существовало - Vulkan с расширением GL_EXT_ray_tracing призван решить эту проблему.
Пайплайн трассировки выглядит, в общих чертах, следующим образом:
- Для каждого пикселя кадра GPU выполняет шейдер генерирования луча (ray generation shader). Он похож на вычислительный шейдер со встроенной функциональностью для обнаружения пересечений геометрии сцены с произвольным лучом.
- При потенциальном пересечении луча со сценой выполняется шейдер пересечения (intersection shader). API трассировки предоставляет готовый оптимизированный шейдер пересечения для треугольников. Пользователь может задать свои шейдеры пересечения для других примитивов и параметрических поверхностей.
- Если обнаружено пересечение, то оно обрабатывается шейдером попадания (hit shader) - именно в нем происходит вычисление цвета пикселя. В противном случае луч передается шейдеру пропуска (miss shader) - он может использоваться, например, для присвоения пикселю цвета фона. Если необходимо, шейдер попадания может генерировать новые лучи - например, чтобы вычислить интеграл освещенности.