FOV · 50°ASPECT · W:HRES · W×H pxBASIS · u, v, w
Rozdział 3 / Podstawy

Model kamery: od piksela do promienia

Wiesz już, jak zapisać promień i jak sprawdzić, czy trafia w sferę. Zostało jedno pytanie: skąd bierze się D? Zamieniamy pozycję kamery, pole widzenia i współrzędne piksela w konkretny wektor kierunku.

TL;DR
Pass: Układ kamery

Baza kamery: forward, right, up

Kamera w ray tracerze to coś więcej niż punkt w przestrzeni — to punkt plus orientacja. Potrzebujemy trzech wzajemnie prostopadłych wektorów jednostkowych, które razem tworzą lokalny układ współrzędnych kamery:

↓ Dodatek F — macierze i współrzędne jednorodne

Skąd wziąć right i up, mając tylko forward i globalny „up świata” (najczęściej (0, 1, 0))? Tu wchodzi nowa operacja: iloczyn wektorowy (cross product). W przeciwieństwie do iloczynu skalarnego z Rozdziału 2, który zwracał liczbę, A × B zwraca wektor — prostopadły jednocześnie do A i do B, zgodnie z regułą prawej ręki.

right = normalize(forward × up_world)
up = right × forwardcross product: wektor prostopadły do obu wejściowych; drugie użycie gwarantuje, że up jest już idealnie prostopadły do forward
Camera.basisu, v, w
forward (w) right (u) up (v) eye (O)
Trzy wzajemnie prostopadłe wektory jednostkowe — lokalny układ współrzędnych kamery.
Pass: FOV i proporcje

Viewport i pole widzenia

Pole widzenia (field of view, FOV) określa, jak „szeroko” kamera widzi scenę — ten sam parametr, który ustawiasz w atrybutach kamery w Mayi czy Blenderze. Umieszczamy wirtualny prostokąt (viewport) w pewnej odległości przed kamerą, wzdłuż forward — i to jego wymiary, nie parametry samej kamery, bezpośrednio wyznaczają kierunki promieni.

viewport_height = 2 · tan(FOV / 2)
viewport_width = aspect · viewport_heightprzy odległości 1 wzdłuż forward; aspect = W / H (szerokość / wysokość obrazu w pikselach)

Większy FOV → większy viewport → promienie rozchodzą się szerzej — typowy „szeroki kąt”. Aspect ratio dba o to, żeby kwadratowe piksele nie rozciągały obrazu — inaczej kula wyjdzie jak jajko.

Fov.aspect2 views
FOV=50° · h=2·tan(FOV/2)=1,86 · aspect=1,57 · w=aspect·h=2,93
WIDOK Z BOKU · FOV WIDOK Z PRZODU · ASPECT FOV h w h
h = viewport_height, w = viewport_width. Ten sam kąt FOV z boku daje konkretny prostokąt z przodu — przesuń oba suwaki niezależnie.
Pass: Pixel → Ray

Od piksela do promienia

Mając bazę kamery i wymiary viewportu, każdy piksel (i, j) obrazu o rozdzielczości W×H zamieniamy na promień w czterech krokach. Najpierw normalizujemy współrzędne piksela do rozmiaru viewportu (czasem nazywane NDC — normalized device coordinates):

s = (2(i + 0.5)/W − 1) · viewport_width / 2
t = (1 − 2(j + 0.5)/H) · viewport_height / 2i, j — indeks piksela; +0.5 bierze środek piksela, nie jego róg; minus przy t, bo j rośnie w dół obrazu, a up w górę

Następnie łączymy to z bazą kamery, żeby dostać punkt na viewporcie w przestrzeni świata, i wyciągamy z niego kierunek:

P = eye + forward + s · right + t · up
D = normalize(P − eye)P — punkt na viewporcie dla danego piksela; D — gotowy, znormalizowany kierunek promienia
Pixel.to.ray3 samples
eye piksel (0,0) środkowy piksel (W−1,H−1)
Każdy piksel to inny punkt na tej samej płaszczyźnie viewportu — i inny promień D.
Z praktyki

Jeśli w Blenderze czy Mayi zmieniasz „focal length” i „sensor size” kamery, a nie FOV bezpośrednio — to i tak przelicza się na dokładnie ten sam kąt:

FOV = 2 · atan( sensor / (2 · focal) )

Dłuższy focal length = mniejszy FOV = bardziej „teleobiektywowy” kadr. To dlatego zbliżenia teleobiektywem spłaszczają perspektywę, a szerokie kąty ją mocno wyginają — to wciąż ten sam wzór z tego rozdziału, tylko schowany za innymi nazwami sliderów.

Słowniczek
Forward (look/view vector)
Kierunek, w który patrzy kamera.
Right, up
Wektory dopełniające bazę kamery, prostopadłe do forward i do siebie.
Iloczyn wektorowy (cross product)
Operacja A × B zwracająca wektor prostopadły do obu wejściowych.
Ortonormalna baza
Trzy wektory jednostkowe, wzajemnie prostopadłe — tu: forward, right, up.
Pole widzenia (FOV)
Kąt, jak szeroko kamera widzi scenę; wyznacza rozmiar viewportu.
Proporcje obrazu (aspect ratio)
W / H — zapobiega rozciąganiu obrazu przy niekwadratowych rozdzielczościach.
Viewport / NDC
Wirtualna płaszczyzna przed kamerą, na którą mapowane są piksele obrazu.
Idź głębiej
Dodatek F — Macierze i współrzędne jednorodne