Przejdź do zawartości

Śledzenie promieni: Różnice pomiędzy wersjami

Z Wikipedii, wolnej encyklopedii
[wersja nieprzejrzana][wersja przejrzana]
Usunięta treść Dodana treść
→‎Algorytm: wyznaczanie promieni dla prostokątnej rzutni
m kat.
 
(Nie pokazano 37 wersji utworzonych przez 16 użytkowników)
Linia 1: Linia 1:
[[Plik:Raytracing reflection.png|thumb|right|300px|Scena wygenerowana metodą śledzenia promieni, w której wszystkie obiekty odbijają światło]]
[[Plik:Raytracing reflection.png|thumb|300px|Scena wygenerowana metodą śledzenia promieni, w której wszystkie obiekty odbijają światło]]
{{Dopracować|źródła=2021-03}}
'''Śledzenie promieni''', '''wsteczne śledzenie promieni''' ({{Ang.|ray tracing, backward raytracing}}) – technika generowania [[fotorealizm (grafika komputerowa)|fotorealistycznych]] obrazów scen [[Grafika 3D|trójwymiarowych]] opierająca się na analizowaniu tylko tych promieni światła, które trafiają bezpośrednio do obserwatora. W [[Rekurencja|rekursywnym]] śledzeniu promieni bada się dodatkowo promienie odbite, zwierciadlane oraz [[Prawo Snelliusa|załamane]]. Ponadto umożliwia łatwą realizację [[CSG]], a także wizualizację idealnych, opisywanych formułami matematycznymi obiektów. Odwrotne podejście do techniki śledzenia promieni realizuje metoda ''[[Forward raytracing|prostego śledzenie promieni]]'' (ang. ''forward raytracing'').
'''Śledzenie promieni''', '''wsteczne śledzenie promieni''' ({{Ang.|ray tracing}}, {{k|en|backward raytracing}}) – technika generowania [[fotorealizm (grafika komputerowa)|fotorealistycznych]] obrazów scen [[Grafika 3D|trójwymiarowych]] opierająca się na analizowaniu tylko tych promieni światła, które trafiają bezpośrednio do obserwatora. W [[Rekurencja|rekursywnym]] śledzeniu promieni bada się dodatkowo promienie odbite, zwierciadlane oraz [[Prawo Snelliusa|załamane]]. Ponadto umożliwia łatwą realizację [[CSG]], a także wizualizację idealnych, opisywanych formułami matematycznymi obiektów. Odwrotne podejście do techniki śledzenia promieni realizuje metoda ''[[Forward raytracing|prostego śledzenie promieni]]'' (ang. {{K|en|forward raytracing}}).


Metoda mimo uproszczonego modelu interakcji światła z otoczeniem daje bardzo dobre rezultaty, jednak ze względu na koszty obliczeniowe przez wiele lat jej wykorzystanie limitowała moc obliczeniowa komputerów, które były dostępne tylko dla dużych firm, głównie z branży filmowej. Współczesne [[komputer osobisty|komputery osobiste]] są w stanie bez problemu generować obrazy tą metodą i dostępne są komercyjne oraz darmowe programy ([[POV-Ray]], [[Blender (program)|Blender]], [[3ds Max]], [[Maya (program komputerowy)|Maya]], [[LightWave 3D]], [[PYTHA]]).
Metoda mimo uproszczonego modelu interakcji światła z otoczeniem daje bardzo dobre rezultaty, jednak ze względu na koszty obliczeniowe przez wiele lat jej wykorzystanie limitowała [[moc obliczeniowa]] komputerów, które były dostępne tylko dla dużych firm, głównie z branży filmowej. Współczesne [[komputer osobisty|komputery osobiste]] są w stanie bez problemu generować obrazy tą metodą i dostępne są komercyjne oraz darmowe programy ([[POV-Ray]], [[Blender (program)|Blender]], [[3ds Max]], [[Maya (program komputerowy)|Maya]], [[LightWave 3D]], [[PYTHA]]).


== Algorytm ==
== Algorytm ==
{{Zobacz też|algorytm}}
{{Zobacz też|algorytm}}
[[Plik:Raytracing-schemat.png|thumb|300px|Sposób określania barwy piksela w śledzeniu promieni]]
[[Plik:Raytracing-schemat.png|thumb|300px|Sposób określania barwy piksela w śledzeniu promieni]]
Algorytm śledzenia promieni wygląda następująco:
[[Algorytm]] śledzenia promieni wygląda następująco:
# Z punktu w którym znajduje się obserwator wyprowadzany jest promień pierwotny, który przecina rzutnię.
# Z punktu, w którym znajduje się obserwator, wyprowadzany jest promień pierwotny, który przecina rzutnię.
# Wyszukiwany jest najbliższy punkt przecięcia z obiektami znajdującymi się na scenie.
# Wyszukiwany jest najbliższy punkt przecięcia z obiektami znajdującymi się na scenie.
# Następnie dla każdego źródła światła zdefiniowanego na scenie wyznaczana jest jasność w tym punkcie, zgodnie z określonym modelem oświetlenia (np. [[Odbicie lambertowskie|Lamberta]] czy [[Cieniowanie Phonga|Phonga]]).<br />Najczęściej także określa się cienie – w tym celu jest testowana widoczność źródła światła z danego punktu, tj. czy światło nie jest przesłaniane przez jakiś obiekt i jeśli nie – dopiero wtedy oblicza się jasność punktu dla tego źródła.
# Następnie dla każdego źródła światła zdefiniowanego na scenie wyznaczana jest jasność w tym punkcie, zgodnie z określonym modelem oświetlenia (np. [[Odbicie lambertowskie|Lamberta]] czy [[Cieniowanie Phonga|Phonga]]).<br>Najczęściej także określa się cienie – w tym celu jest testowana widoczność źródła światła z danego punktu, tj. czy światło nie jest przesłaniane przez jakiś obiekt i jeśli nie – dopiero wtedy oblicza się jasność punktu dla tego źródła.


W algorytmie rekurencyjnym dodaje się jeszcze jeden warunek:
W algorytmie rekurencyjnym dodaje się jeszcze jeden warunek:
: Jeśli punkt przecięcia należy do obiektu odbijającego światło lub przezroczystego, wysyłane są z tego punktu promienie wtórne – odpowiednio, promień odbity lub promień załamany – i algorytm rekursywnie powtarza się od drugiego kroku (w większości programów można ograniczyć liczbę zejść rekurencyjnych). Kolor punktu wyznaczany jest dopiero, gdy znane są wyniki przetwarzania promieni wtórnych; zwykle projektant podaje procentowo wpływ kolorów z promieni wtórnych, tj. określa jak bardzo obiekt odbija/załamuje światło.
: Jeśli punkt przecięcia należy do obiektu odbijającego światło lub przezroczystego, wysyłane są z tego punktu promienie wtórne – odpowiednio, promień odbity lub promień załamany – i algorytm rekursywnie powtarza się od drugiego kroku (w większości programów można ograniczyć liczbę zejść rekurencyjnych). Kolor punktu wyznaczany jest, dopiero gdy znane są wyniki przetwarzania promieni wtórnych; zwykle projektant podaje procentowo wpływ kolorów z promieni wtórnych, tj. określa jak bardzo obiekt odbija/załamuje światło.


Algorytm śledzenia promieni stosuje się dla wszystkich [[piksel]]i obrazu; aby uniknąć [[aliasing (grafika komputerowa)|aliasingu]] przez jeden piksel przeprowadza się więcej niż jeden promień.
Algorytm śledzenia promieni stosuje się dla wszystkich [[piksel]]i obrazu; aby uniknąć [[aliasing (grafika komputerowa)|aliasingu]] przez jeden piksel przeprowadza się więcej niż jeden promień.
Linia 19: Linia 20:
Bardzo dużą zaletą tej metody jest łatwość przeprowadzenia [[obliczenia równoległe|obliczeń równoległych]], gdyż każdy promień pierwotny może być przetwarzany niezależnie od innych; podobnie promienie wtórne są od siebie niezależne.
Bardzo dużą zaletą tej metody jest łatwość przeprowadzenia [[obliczenia równoległe|obliczeń równoległych]], gdyż każdy promień pierwotny może być przetwarzany niezależnie od innych; podobnie promienie wtórne są od siebie niezależne.


Obecnie śledzenie promieni implementuje się również w [[Procesor graficzny|procesorach graficznych]] uzyskując obrazy w czasie rzeczywistym (kilkanaście-kilkadziesiąt klatek na sekundę).
Obecnie śledzenie promieni implementuje się również w [[Procesor graficzny|procesorach graficznych]], uzyskując obrazy w czasie rzeczywistym (kilkanaście-kilkadziesiąt [[Klatki na sekundę|klatek na sekundę]]).


: {| class="toccolours collapsible collapsed" width="60%" style="text-align:left;"
=== Przykład ===
!Detale dotyczące wyznaczenia promienia dla piksela na prostokątnej rzutni
[[Plik:Recursive raytracing.svg|thumb|300px|Zasada działania rekursywnego algorytmu śledzenia promieni]]
|-
Obserwator (kamera) znajduje się w punkcie '''O''', na scenie umieszczone zostały dwa światła L1 i L2 oraz trzy obiekty:
|
* '''a''' (elipsa): nieprzezroczysty, nie odbija światła,
Na wejściu dane mamy (w obliczeniach korzystamy z [[Wektor#Wektor jednostkowy|normalizacji wektora]] oraz [[Wektor#Iloczyn wektorowy|iloczynu wektorowego]]):
* '''b''' (koło): przezroczysty, odbija światło,
* <math>E \in \mathbb{R^3}</math> pozycja oka,
* '''c''' (prostokąt): tylko odbija światło.
* <math>T \in \mathbb{R^3}</math> pozycja celu,

* <math>\theta \in [0,\pi)</math> [[pole widzenia]] dla człowieka można przyjąć <math>\approx \pi/2 \text{ rad}= 90^\circ,</math>
Z punktu '''O''' wyprowadzany jest promień pierwotny (zielony), który trafia w obiekt '''b''' – ponieważ odbija i załamuje światło, toteż z punktu przecięcia wypuszczane są dwa promienie wtórne: odbity (czerwony) i załamany (niebieski). Promień odbity trafia z kolei w obiekt '''a''' – tutaj już nie są generowane żadne promienie wtórne. Z kolei promień załamany znów trafia w obiekt '''b''' i ponownie ulega załamaniu (tak naprawdę powinien tutaj być jeszcze promień odbity, ale ze względu na przejrzystość rysunku został pominięty). Ten promień trafia w obiekt '''c''', który odbija światło, toteż generowany jest tylko jeden promień wtórny (odbity), który jednak nie przecina się z żadnym obiektem na scenie i na tym kończy się analiza.
* <math>m,k \in \mathbb{N}</math> liczba kwadratowych pikseli odpowiednio na wysokości i szerokości rzutni,

* <math>i,j \in \mathbb{N}, 1\leqslant i\leqslant k \land 1\leqslant j\leqslant m</math> numery/współrzędne aktualnego piksela,
Kreskami przerywanymi zaznaczono dodatkowe promienie, służące określeniu widoczności świateł w punktach przecięcia (dla punktów obiektu '''b''' te promienie nie zostały narysowane) – jak widać zarówno inne obiekty ('''b''') jak i sam obiekt ('''a''') może blokować światło.
* <math>\vec w \in \mathbb{R^3}</math> wektor pionu, wyznaczający gdzie jest góra a gdzie dół, zwykle <math>\vec w = [0,1,0]</math> (nie pokazano na rysunku) – determinuje on [[Kąty RPY|komponent roll]] określający obrót rzutni wokół punktu C (gdzie osią obrotu jest odcinek ET).

=== Wyznaczanie promieni dla prostokątnej rzutni ===

Na wejściu dane mamy (punkty oznaczamy dużymi literami, wektory i skalary małymi):

* <math>E \in \mathbb{R^3}</math> pozycja oka
* <math>T \in \mathbb{R^3}</math> pozycja celu
* <math>\theta \in [0,\pi) </math> pole widzenia - dla człowieka <math>\approx \pi/2 \text{ rad}= 90^\circ</math>
* <math>m,k \in \mathbb{N}</math> liczba kwadratowych pikseli odpowiednio na wysokości i szerokości rzutni
* <math>i,j \in \mathbb{N}, 1\leq i\leq k \and 1\leq j\leq m </math> numer aktualnego piksela
* <math>\vec w \in \mathbb{R^3}</math> wektor pionu, wyznaczający gdzie jest góra a gdzie dół, zwykle <math>w = [0,1,0]</math> (nie pokazano na rysunku)


[[Plik:RaysViewportSchema.png|708px|Schemat rzutni wraz z pikselami, okiem (E) i celem (T)]]
[[Plik:RaysViewportSchema.png|708px|Schemat rzutni wraz z pikselami, okiem (E) i celem (T)]]


Idea polega na znalezieniu pozycji środka każdego piksela na rzutni <math>P_{ij}</math> co łatwo dalej pozwoli znaleźć prostą przechodzącą przezeń i punkt <math>E</math> i w konsekwencji sam promień opisany jako para <math>E</math> i znormalizowany wektor <math>\vec r_{ij}</math>. Aby to zrobić wystarczy że znajdziemy położenie lewego dolnego piksela <math>P_{1m}</math> a kolejne piksele poprzez odpowiednie przesunięcia (o wielokrotność wielkości piksela) wzdłuż kierunków prostopadłych do rzutni (wektory <math>\vec b</math> i <math>\vec v</math>). Poniżej wyprowadzimy zależności uwzględniając odległość <math>d</math> oka od rzutni, jednak ta wartość skróci się podczas normalizacji wynikowego wektora <math>\vec r_{ij}</math> (więc równie dobrze można przyjąć że <math>d=1</math> i usunąć z obliczeń). Obliczenia wstępne: obliczymy znormalizowane wektory <math>v_n, b_n</math> (patrz rysunek powyżej) prostopadłe do rzutni
Idea polega na znalezieniu pozycji środka każdego piksela na rzutni <math>P_{ij}</math> co łatwo dalej pozwoli znaleźć prostą przechodzącą przezeń i punkt <math>E</math> i w konsekwencji sam promień opisany jako para <math>E</math> i wektor <math>\vec R_{ij} = P_{ij} -E</math> (lub jego znormalizowana wersja <math>\vec r_{ij}</math>). Aby to zrobić wystarczy, że znajdziemy położenie lewego dolnego piksela <math>P_{1m}</math> a kolejne piksele poprzez odpowiednie przesunięcia (o wielokrotność wielkości piksela) wzdłuż kierunków równoległych do rzutni (wektory <math>\vec b</math> i <math>\vec v</math>). Poniżej wyprowadzimy zależności uwzględniając odległość <math>d</math> oka od rzutni, jednak ta wartość skróci się podczas normalizacji wynikowego wektora <math>\vec r_{ij}</math> (więc równie dobrze można przyjąć, że <math>d=1</math> i usunąć z obliczeń). Obliczenia wstępne: obliczymy znormalizowane wektory <math>\vec v_n, \vec b_n</math> (patrz rysunek powyżej) równoległe do rzutni
: <math>\vec t = T-E, \qquad \vec b = \vec w\times \vec t,</math>


:<math>
: <math>
\vec t_n = \frac{\vec t}{||\vec t||}, \qquad
t = T-E, \qquad b = w\times t
\vec b_n = \frac{\vec b}{||\vec b||}, \qquad
</math>
\vec v_n = \vec t_n\times \vec b_n.</math>


zauważmy że: <math>C=E+\vec t_nd,</math> następnie obliczamy wielkości rzutni <math>h_x, h_y</math> podzielone przez 2 z uwzględnieniem [[Format obrazu|formatu obrazu]], tj. stosunku <math>\frac{m}{k}{:}</math>
:<math>
: <math>g_x=\frac{h_x}{2} =d \operatorname{tg} \frac{\theta}{2}, \qquad g_y =\frac{h_y}{2} = g_x \frac{m}{k},</math>
t_n = \frac{t}{||t||}, \qquad
b_n = \frac{b}{||b||}, \qquad
v_n = t_n\times b_n
</math>


zauważmy że: <math>C=E+t_nd</math>, następnie obliczamy wielkości rzutni <math>h_x, h_y</math> podzielone przez 2 z uwzględnieniem [[Format obrazu|stosunku tych dwóch]] wielkości <math>\frac{m}{k}</math> :
a następnie obliczymy wektory przesunięcia <math>q_x,q_y</math> wzdłuż kierunków prostopadłych do rzutni <math>(\vec b,\vec v)</math>
: <math>
\vec q_x = \frac{2g_x}{k-1}\vec b_n, \qquad
\vec q_y = \frac{2g_y}{m-1}\vec v_n, \qquad
\vec p_{1m} = \vec t_n d - g_x\vec b_n - g_y\vec v_n.</math>


Obliczenia właściwe: zauważmy, że <math>P_{ij} = E + \vec p_{ij}</math> oraz że promień <math>\vec R_{ij} = P_{ij} -E = \vec p_{ij}</math> zatem
:<math>
: <math>\vec p_{ij} = \vec p_{1m} + \vec q_x(i-1) + \vec q_y(j-1),</math>
g_x=\frac{h_x}{2} =d \tan \frac{\theta}{2}, \qquad g_y =\frac{h_y}{2} = g_x \frac{m}{k}
: <math>\vec r_{ij} = \frac{\vec R_{ij}}{||\vec R_{ij}||} = \frac{\vec p_{ij}}{||\vec p_{ij}||}.</math>
</math>


Powyższa formuła została przetestowana w tym [https://kamil-kielczewski.github.io/fractals/mandelbulb.html projekcie javascript] (działa w przeglądarce).
a następnie obliczymy wektory przesunięcia <math>q_x,q_y</math> wzdłuż kierunków prostopadłych do rzutni (<math>\vec b,\vec v</math>)
|}


=== Przykład ===
:<math>
[[Plik:Recursive raytracing.svg|thumb|300px|Zasada działania rekursywnego algorytmu śledzenia promieni]]
q_x = \frac{2g_x}{k-1}b_n, \qquad
Obserwator (kamera) znajduje się w punkcie '''O''', na scenie umieszczone zostały dwa światła L1 i L2 oraz trzy obiekty:
q_y = \frac{2g_y}{m-1}v_n, \qquad
* '''a''' (elipsa): nieprzezroczysty, nie odbija światła,
p_{1m} = t_n d - g_xb_n - g_yv_n
* '''b''' (koło): przezroczysty, odbija światło,
</math>
* '''c''' (prostokąt): tylko odbija światło.


Z punktu '''O''' wyprowadzany jest promień pierwotny (zielony), który trafia w obiekt '''b''' – ponieważ odbija i załamuje światło, toteż z punktu przecięcia wypuszczane są dwa promienie wtórne: odbity (czerwony) i załamany (niebieski). Promień odbity trafia z kolei w obiekt '''a''' – tutaj już nie są generowane żadne promienie wtórne. Z kolei promień załamany znów trafia w obiekt '''b''' i ponownie ulega załamaniu (tak naprawdę powinien tutaj być jeszcze promień odbity, ale ze względu na przejrzystość rysunku został pominięty). Ten promień trafia w obiekt '''c''', który odbija światło, toteż generowany jest tylko jeden promień wtórny (odbity), który jednak nie przecina się z żadnym obiektem na scenie i na tym kończy się analiza.


Kreskami przerywanymi zaznaczono dodatkowe promienie, służące określeniu widoczności świateł w punktach przecięcia (dla punktów obiektu '''b''' te promienie nie zostały narysowane) – jak widać zarówno inne obiekty ('''b'''), jak i sam obiekt ('''a''') może blokować światło.
Obliczenia właściwe: zauważmy że <math>P_{ij} = E + p_{ij}</math> oraz że promień <math>R_{ij} = P_{ij} -E = p_{ij}</math> zatem

:<math>
p_{ij} = p_{11} + q_x(i-1) + q_y(j-1)
</math>
:<math>
r_{ij} = \frac{p_{ij}}{||p_{ij}||}
</math>

Powyższa formuła została przetestowana w tym [https://kamil-kielczewski.github.io/fractals/mandelbulb.html projekcie javascript] [here][1] (działa w przeglądarce).

[1]: https://kamil-kielczewski.github.io/fractals/mandelbulb.html


== Złożoność obliczeniowa ==
== Złożoność obliczeniowa ==
Linia 89: Linia 75:
Śledzenie promieni jest metodą kosztowną obliczeniowo – liczba obliczeń jest proporcjonalna do rozdzielczości obrazu, zależy również od stopnia skomplikowania sceny, tj. od liczby świateł (wyznaczenie cieni), liczby obiektów oraz ich charakterystyki: jeśli bowiem zawiera dużą liczbę obiektów odbijających lub załamujących światło należy przeprowadzać analizę także dla promieni wtórnych.
Śledzenie promieni jest metodą kosztowną obliczeniowo – liczba obliczeń jest proporcjonalna do rozdzielczości obrazu, zależy również od stopnia skomplikowania sceny, tj. od liczby świateł (wyznaczenie cieni), liczby obiektów oraz ich charakterystyki: jeśli bowiem zawiera dużą liczbę obiektów odbijających lub załamujących światło należy przeprowadzać analizę także dla promieni wtórnych.


Zasadniczym czynnikiem wpływającym na szybkość obliczeń jest procedura znajdowania najbliższego przecięcia promienia z obiektami geometrycznymi. Np. wyznaczenie przecięcia z kulą wymaga rozwiązania [[równanie kwadratowe|równania kwadratowego]], a przecięcia z płaszczyzną rozwiązania [[równanie liniowe|równania liniowego]] (ale już dla wycinków płaszczyzny, np. wielokątów, wymaga dodatkowych testów). Z kolei dla obiektów bardziej skomplikowanych, jak [[torus (matematyka)|torusy]], [[bryła obrotowa|bryły obrotowe]], [[płaty Béziera]], czy [[NURBS]] potrzebne są złożone obliczenia.
Zasadniczym czynnikiem wpływającym na szybkość obliczeń jest procedura znajdowania najbliższego przecięcia promienia z obiektami geometrycznymi. Np. wyznaczenie przecięcia z kulą wymaga rozwiązania [[równanie kwadratowe|równania kwadratowego]], a przecięcia z płaszczyzną rozwiązania [[równanie liniowe|równania liniowego]] (ale już dla wycinków płaszczyzny, np. wielokątów, wymaga dodatkowych testów). Z kolei dla obiektów bardziej skomplikowanych, jak [[torus (matematyka)|torusy]], [[bryła obrotowa|bryły obrotowe]], [[płaty Béziera]] czy [[NURBS]] potrzebne są złożone obliczenia.


Nie mniej ważnym problemem jest wytypowanie tych obiektów ze sceny, które ''mogą'' się z danym promieniem przeciąć – aby procedury przeprowadzające dokładne obliczenia wywoływać tylko wtedy, gdy jest to niezbędne; mówiąc obrazowo: jeśli scena zawiera milion obiektów, by za każdym razem nie testować milion razy, czy promień przecina każdy z nich. Jednym ze sposobów na minimalizację obliczeń jest podział przestrzenny sceny (regularną siatką, [[drzewo ósemkowe|drzewami ósemkowymi]], [[Drzewo kd|kd]], czy [[Binary space partitioning|BSP]]), powszechnie wykorzystuje się także [[Bryła brzegowa|bryły otaczające]] (pozwalające szybciej określić czy promień ''może'' mieć punkt wspólny z obiektem, bądź że na pewno go nie ma).
Nie mniej ważnym problemem jest wytypowanie tych obiektów ze sceny, które ''mogą'' się z danym promieniem przeciąć – aby procedury przeprowadzające dokładne obliczenia wywoływać tylko wtedy, gdy jest to niezbędne; mówiąc obrazowo: jeśli scena zawiera milion obiektów, by za każdym razem nie testować milion razy, czy promień przecina każdy z nich. Jednym ze sposobów na minimalizację obliczeń jest podział przestrzenny sceny (regularną siatką, [[drzewo ósemkowe|drzewami ósemkowymi]], [[Drzewo kd|kd]], czy [[Binary space partitioning|BSP]]), powszechnie wykorzystuje się także [[Bryła brzegowa|bryły otaczające]] (pozwalające szybciej określić czy promień ''może'' mieć punkt wspólny z obiektem, bądź że na pewno go nie ma).
Linia 99: Linia 85:


== Zobacz też ==
== Zobacz też ==
* [[ambient occlusion]]
* [[Carmack’s Reverse]]
* [[cieniowanie]]
* [[Oświetlenie (grafika komputerowa)|oświetlenie]]
* [[renderowanie]]
* [[renderowanie]]
*[[shader]]
* [[shader]]

*[[cieniowanie]]
{{Kontrola autorytatywna}}
*[[Oświetlenie (grafika komputerowa)|oświetlenie]]
*[[ambient occlusion]]
*[[Carmack’s Reverse]]


[[Kategoria:Rendering]]
[[Kategoria:Rendering]]
[[Kategoria:Grafika trójwymiarowa]]

Aktualna wersja na dzień 10:46, 19 wrz 2024

Scena wygenerowana metodą śledzenia promieni, w której wszystkie obiekty odbijają światło

Śledzenie promieni, wsteczne śledzenie promieni (ang. ray tracing, backward raytracing) – technika generowania fotorealistycznych obrazów scen trójwymiarowych opierająca się na analizowaniu tylko tych promieni światła, które trafiają bezpośrednio do obserwatora. W rekursywnym śledzeniu promieni bada się dodatkowo promienie odbite, zwierciadlane oraz załamane. Ponadto umożliwia łatwą realizację CSG, a także wizualizację idealnych, opisywanych formułami matematycznymi obiektów. Odwrotne podejście do techniki śledzenia promieni realizuje metoda prostego śledzenie promieni (ang. forward raytracing).

Metoda mimo uproszczonego modelu interakcji światła z otoczeniem daje bardzo dobre rezultaty, jednak ze względu na koszty obliczeniowe przez wiele lat jej wykorzystanie limitowała moc obliczeniowa komputerów, które były dostępne tylko dla dużych firm, głównie z branży filmowej. Współczesne komputery osobiste są w stanie bez problemu generować obrazy tą metodą i dostępne są komercyjne oraz darmowe programy (POV-Ray, Blender, 3ds Max, Maya, LightWave 3D, PYTHA).

Algorytm

[edytuj | edytuj kod]
 Zobacz też: algorytm.
Sposób określania barwy piksela w śledzeniu promieni

Algorytm śledzenia promieni wygląda następująco:

  1. Z punktu, w którym znajduje się obserwator, wyprowadzany jest promień pierwotny, który przecina rzutnię.
  2. Wyszukiwany jest najbliższy punkt przecięcia z obiektami znajdującymi się na scenie.
  3. Następnie dla każdego źródła światła zdefiniowanego na scenie wyznaczana jest jasność w tym punkcie, zgodnie z określonym modelem oświetlenia (np. Lamberta czy Phonga).
    Najczęściej także określa się cienie – w tym celu jest testowana widoczność źródła światła z danego punktu, tj. czy światło nie jest przesłaniane przez jakiś obiekt i jeśli nie – dopiero wtedy oblicza się jasność punktu dla tego źródła.

W algorytmie rekurencyjnym dodaje się jeszcze jeden warunek:

Jeśli punkt przecięcia należy do obiektu odbijającego światło lub przezroczystego, wysyłane są z tego punktu promienie wtórne – odpowiednio, promień odbity lub promień załamany – i algorytm rekursywnie powtarza się od drugiego kroku (w większości programów można ograniczyć liczbę zejść rekurencyjnych). Kolor punktu wyznaczany jest, dopiero gdy znane są wyniki przetwarzania promieni wtórnych; zwykle projektant podaje procentowo wpływ kolorów z promieni wtórnych, tj. określa jak bardzo obiekt odbija/załamuje światło.

Algorytm śledzenia promieni stosuje się dla wszystkich pikseli obrazu; aby uniknąć aliasingu przez jeden piksel przeprowadza się więcej niż jeden promień.

Bardzo dużą zaletą tej metody jest łatwość przeprowadzenia obliczeń równoległych, gdyż każdy promień pierwotny może być przetwarzany niezależnie od innych; podobnie promienie wtórne są od siebie niezależne.

Obecnie śledzenie promieni implementuje się również w procesorach graficznych, uzyskując obrazy w czasie rzeczywistym (kilkanaście-kilkadziesiąt klatek na sekundę).

Przykład

[edytuj | edytuj kod]
Zasada działania rekursywnego algorytmu śledzenia promieni

Obserwator (kamera) znajduje się w punkcie O, na scenie umieszczone zostały dwa światła L1 i L2 oraz trzy obiekty:

  • a (elipsa): nieprzezroczysty, nie odbija światła,
  • b (koło): przezroczysty, odbija światło,
  • c (prostokąt): tylko odbija światło.

Z punktu O wyprowadzany jest promień pierwotny (zielony), który trafia w obiekt b – ponieważ odbija i załamuje światło, toteż z punktu przecięcia wypuszczane są dwa promienie wtórne: odbity (czerwony) i załamany (niebieski). Promień odbity trafia z kolei w obiekt a – tutaj już nie są generowane żadne promienie wtórne. Z kolei promień załamany znów trafia w obiekt b i ponownie ulega załamaniu (tak naprawdę powinien tutaj być jeszcze promień odbity, ale ze względu na przejrzystość rysunku został pominięty). Ten promień trafia w obiekt c, który odbija światło, toteż generowany jest tylko jeden promień wtórny (odbity), który jednak nie przecina się z żadnym obiektem na scenie i na tym kończy się analiza.

Kreskami przerywanymi zaznaczono dodatkowe promienie, służące określeniu widoczności świateł w punktach przecięcia (dla punktów obiektu b te promienie nie zostały narysowane) – jak widać zarówno inne obiekty (b), jak i sam obiekt (a) może blokować światło.

Złożoność obliczeniowa

[edytuj | edytuj kod]

Śledzenie promieni jest metodą kosztowną obliczeniowo – liczba obliczeń jest proporcjonalna do rozdzielczości obrazu, zależy również od stopnia skomplikowania sceny, tj. od liczby świateł (wyznaczenie cieni), liczby obiektów oraz ich charakterystyki: jeśli bowiem zawiera dużą liczbę obiektów odbijających lub załamujących światło należy przeprowadzać analizę także dla promieni wtórnych.

Zasadniczym czynnikiem wpływającym na szybkość obliczeń jest procedura znajdowania najbliższego przecięcia promienia z obiektami geometrycznymi. Np. wyznaczenie przecięcia z kulą wymaga rozwiązania równania kwadratowego, a przecięcia z płaszczyzną rozwiązania równania liniowego (ale już dla wycinków płaszczyzny, np. wielokątów, wymaga dodatkowych testów). Z kolei dla obiektów bardziej skomplikowanych, jak torusy, bryły obrotowe, płaty Béziera czy NURBS potrzebne są złożone obliczenia.

Nie mniej ważnym problemem jest wytypowanie tych obiektów ze sceny, które mogą się z danym promieniem przeciąć – aby procedury przeprowadzające dokładne obliczenia wywoływać tylko wtedy, gdy jest to niezbędne; mówiąc obrazowo: jeśli scena zawiera milion obiektów, by za każdym razem nie testować milion razy, czy promień przecina każdy z nich. Jednym ze sposobów na minimalizację obliczeń jest podział przestrzenny sceny (regularną siatką, drzewami ósemkowymi, kd, czy BSP), powszechnie wykorzystuje się także bryły otaczające (pozwalające szybciej określić czy promień może mieć punkt wspólny z obiektem, bądź że na pewno go nie ma).

Śledzenie promieni, mimo swoich zalet, nie jest idealnym sposobem tworzenia fotorealistycznych obrazów. Przede wszystkim w ogóle nie uwzględnia światła rozproszonego, ponadto ponieważ operuje na pojedynczych promieniach, nie może prawidłowo modelować dyfrakcji, rozszczepienia światła np. na pryzmacie, interferencji fal świetlnych i innych zjawisk falowych.

Stworzono wiele technik, które stosowane samodzielnie bądź w połączeniu ze śledzeniem promieni umożliwiają pokonanie tych niedogodności; są to m.in. metoda energetyczna, śledzenie ścieżek, metoda map fotonowych i tzw. forward raytracing.

Zobacz też

[edytuj | edytuj kod]