Рейтрейсинг против растеризации

Растеризация спрашивает «куда попадёт треугольник», а трассировка лучей — «что увидит луч из камеры».

Рейтрейсинг (трассировка лучей) — метод рендеринга, при котором из камеры через каждый пиксель пускают луч и ищут, с чем он пересечётся, прослеживая отражения и тени.

Зачем это знать

Два подхода решают одну задачу — нарисовать сцену — но с противоположных сторон. Растеризация проецирует геометрию на экран (быстро, основа игр). Рейтрейсинг моделирует физику света (точные отражения, преломления, мягкие тени, но дорого). Современные движки их сочетают, поэтому полезно понимать оба.

Две противоположные стратегии

РастеризацияРейтрейсинг
Вопроскуда попадёт треугольник?что увидит луч?
Направлениегеометрия → экранэкран → геометрия
Отражениятрюки (карты, экраны)естественны
Скоростьочень быстродорого
Растеризация:                Рейтрейсинг:
 треугольник                   камера
     | проецируем               | луч
     v на пиксели               v пускаем в сцену
  [экран]                    [сцена] -> что пересёк луч?

Пересечение луча с объектом

Сердце рейтрейсинга — найти, где луч встречает поверхность. Покажем простейший случай: пересечение луча со сферой. Луч идёт из точки origin в направлении dir; решаем, попал ли он в сферу.

import math

def ray_sphere(origin, dir, center, radius):
    # вектор от камеры к центру сферы
    oc = tuple(o - c for o, c in zip(origin, center))
    a = sum(d*d for d in dir)
    b = 2 * sum(o*d for o, d in zip(oc, dir))
    c = sum(o*o for o in oc) - radius*radius
    disc = b*b - 4*a*c
    if disc < 0:
        return None  # промах
    t = (-b - math.sqrt(disc)) / (2*a)  # ближайшее пересечение
    return round(t, 3)

cam = (0, 0, 0)
forward = (0, 0, -1)
print("Луч в сферу z=-5:", ray_sphere(cam, forward, (0, 0, -5), 1))
print("Луч мимо (сдвиг по y):", ray_sphere(cam, (0, 1, 0), (0, 0, -5), 1))

Вывод:

Луч в сферу z=-5: 4.0
Луч мимо (сдвиг по y): None

Луч вперёд попал в сферу на расстоянии 4.0 (до ближней стенки сферы радиуса 1 на z=-5); луч вверх прошёл мимо. На таких пересечениях строится вся трассировка.

Почему рейтрейсинг дорог

Один первичный луч на пиксель — это только начало. Для отражений и теней из точки пересечения пускают вторичные лучи, из них — ещё, и каждый проверяют против всей геометрии. Число лучей и проверок взрывается.

pixels = 1920 * 1080
rays_per_pixel = 1 + 2 + 4   # первичный + тени + отражения (грубо)
total = pixels * rays_per_pixel
print("Пикселей:", pixels)
print("Лучей всего:", total)
print("И каждый луч проверяется против тысяч треугольников...")

Вывод:

Пикселей: 2073600
Лучей всего: 14515200
И каждый луч проверяется против тысяч треугольников...

Как работает под капотом

Чтобы не проверять каждый луч против каждого треугольника, сцену укладывают в ускоряющую структуру (BVH — иерархия ограничивающих объёмов): луч быстро отсекает целые группы геометрии. Современные GPU имеют аппаратные блоки RT-ядра для пересечений. На практике делают гибрид: основная картинка растеризуется, а рейтрейсингом добавляют отражения, тени и глобальное освещение. Шум от малого числа лучей убирают денойзером.

Частые ошибки

  • Считать рейтрейсинг «всегда лучше» — для большинства задач растеризация быстрее и достаточна.
  • Забыть про ускоряющую структуру (BVH) — наивный перебор немыслимо медленный.
  • Ждать чистой картинки от малого числа лучей — без денойзера будет шум.

Итоги

  • Растеризация: геометрия → экран, быстро; рейтрейсинг: луч из камеры → сцена, физично.
  • Ядро рейтрейсинга — пересечение луча с поверхностью.
  • Дороговизна — от взрыва числа вторичных лучей и проверок.
  • На практике — гибрид: растеризация + рейтрейс-эффекты, ускорение через BVH и денойзинг.
Проверьте себя
1. В каком направлении работает трассировка лучей?
AГеометрия проецируется на экран
BИз камеры через пиксель пускают луч в сцену
CИз света на все объекты сразу
DСнизу вверх по пикселям
2. Почему рейтрейсинг дороже растеризации?
AОн использует CPU
BЧисло вторичных лучей (тени, отражения) и проверок взрывается
CОн рисует больше пикселей
DОн не использует GPU
3. Зачем нужна структура BVH в рейтрейсинге?
AДля хранения текстур
BЧтобы луч быстро отсекал целые группы геометрии вместо перебора всех треугольников
CДля блендинга
DДля теней