Śledzenie promieni (ang. ray tracing) jest pierwszą metodą wizualizacji obiektów trójwymiarowych, od której ludzie zaczęli mówić o ,,fotorealistycznych” obrazach utworzonych przez komputer. Można ją scharakteryzować za pomocą następujących uwag:
Metoda ta jest algorytmem widoczności (przestrzeni obrazu), co prawda niezbyt sprawnym i dlatego często bywa on wspomagany innymi algorytmami widoczności.
Jest to również algorytm wyznaczania cieni.
Najbardziej charakterystyczna jest możliwość symulowania wielokrotnych odbić zwierciadlanych i załamań światła. Bardziej ograniczone są możliwości otrzymywania półcieni.
Istnieje możliwość stosunkowo łatwego połączenia metody śledzenia promieni z konstrukcyjną geometrią brył i z wizualizacją objętościową (można więc tworzyć obrazy dymu, mgły itd.). Klasa dopuszczalnych obiektów, które można wizualizować tą metodą jest bardzo obszerna.
Łatwo można przeciwdziałać zjawisku aliasu, możliwe są też efekty specjalne, takie jak symulowanie głębi ostrości obiektywu i inne.
Ceną za to wszystko jest duża ilość obliczeń wykonywanych w tym algorytmie, czyli długi (rzędu kilku sekund do nawet godzin) czas tworzenia obrazu. Nie jest to więc algorytm nadający się do wykorzystania w programach interakcyjnych jako główna metoda wizualizacji trójwymiarowych scen.
W metodzie śledzenia promieni kolejno dla każdego piksela należy
obliczyć jego barwę, tj. intensywność światła, która dochodzi
do obserwatora ,,przez ten piksel”. W tym celu należy przeszukać
tzw. drzewo promieni.
Korzeniem tego drzewa jest tzw. promień pierwotny, czyli
półprosta o początku w położeniu obserwatora, ,,przechodząca przez
piksel”. Dla danego promienia należy wyznaczyć punkt przecięcia z
powierzchnią obiektu, najbliższy obserwatora. Punkt ten jest początkiem
tzw. promieni wtórnych, których może być kilka (zwykle co
najmniej
Dla każdego z promieni wtórnych wykonuje się podobne obliczenie jak dla promieni pierwotnych. Oczywiście, istnieją ograniczenia w generowaniu promieni wtórnych, które mają na celu zapewnienie własności stopu algorytmu. Dla każdego promienia oblicza się intensywność światła niesionego przez ten promień do jego punktu początkowego. Następnie w punkcie początkowym promieni wtórnych stosuje się odpowiedni model oświetlenia w celu obliczenia intensywności światła niesionego w kierunku początku promienia, który określił ten punkt początkowy promieni wtórnych. Intensywność światła niesionego przez promień pierwotny jest używana do obliczenia barwy piksela.
Dróg, po których porusza się światło jest niewyobrażalnie dużo i dlatego należy wybrać możliwie niewielki zbiór promieni wtórnych, które będą wystarczające do obliczenia intensywności światła z dostateczną dokładnością. Wśród promieni wtórnych wyróżniamy:
promienie odbite, których kierunek wynika z odbicia promienia pierwotnego lub wtórnego niższego rzędu w sposób zwierciadlany:
jeśli |
||||
jeśli |
Uwaga 1: Można zaburzać wektor
Uwaga 2: Czasem wykonuje się też śledzenie promieni odbitych
w inny sposób.
promienie załamane — dla obiektów przezroczystych. Prawo załamania światła jest opisane wzorem
w którym
promienie bezpośredniego oświetlenia — ich kierunki są określone przez położenia źródeł światła. Promienie te służą do uwzględnienia w modelu oświetlenia punktu, który jest ich początkiem, światła dochodzącego bezpośrednio od źródeł. Śledzenie tych promieni ma na celu wyznaczenie odległości od źródeł światła oraz wykrycie ewentualnych obiektów rzucających cień.
Program przeszukuje drzewo promieni metodą DFS. Promienie wtórne są generowane wtedy, gdy są spełnione następujące warunki:
Przypuśćmy, że w obliczeniach intensywności światła
niesionego przez promień jest obliczana zgodnie z modelem oświetlenia
Phonga. Dla każdego promienia obliczamy jego wagę, czyli
współczynnik, który określa wpływ intensywności światła
niesionego przez ten promień na ostateczną barwę piksela. Dla
promieni pierwotnych współczynnik ten jest równy
Jeśli otrzymana waga promienia jest mniejsza niż ustalona wartość
progowa, to nie tracimy czasu na śledzenie tego promienia. Dla
przykładu, w programie RayShade domyślna wartość progowa (odpowiedni
parametr nazywa się cutoff) jest równa
Program śledzenia promieni może też ustalić arbitralne
ograniczenie wysokości drzewa promieni (np. w RayShade mamy parametr
maxdepth o domyślnej wartości
Najwięcej czasu w śledzeniu promieni, do
Jeśli obiekt jest powierzchnią parametryczną,
(litera
Powyższe równanie jest układen trzech równań z trzema niewiadomymi,
Jeśli powierzchnię reprezentujemy w postaci niejawnej:
to po wstawieniu parametrycznej reprezentacji promienia dostajemy
równanie skalarne z jedną niewiadomą
Zauważmy, że równania liniowe otrzymamy wtedy, gdy rozpatrywana powierzchnia jest płaszczyzną, daną w postaci
Wysiłek mający na celu przyspieszenie działania programu do śledzenia promieni może mieć na celu
zmniejszenie kosztu wyznaczania punktu przecięcia promienia z obiektem, albo
zmniejszenie liczby par promień/obiekt, dla których poszukuje się przecięć (zwróćmy uwagę, że jeśli scena składa się z wielu obiektów, to każdy promień przecina tylko nieliczne z nich).
Ilość obliczeń w śledzeniu promieni jest taka, że niezależnie od mocy obliczeniowej komputera (która rośnie w zdumiewającym, ale i tak zbyt wolnym tempie1097th rule of acquisition: “Enough… is never enough.”), do realizacji pierwszego z powyższych celów wciąż jeszcze ludzie sięgają po asembler i optymalizują na tym poziomie procedury jak mało które. Przedtem lepiej jest jednak wybrać algorytm, który wykonuje jak najmniej działań, bo asembler to ostateczność.
Porównamy dwie metody obliczania punktu przecięcia promienia ze sferą.
Zakładamy, że
Metoda 1: Równania promienia i sfery mają postać
Po podstawieniu otrzymujemy równanie
dalej możemy obliczyć
Metoda 2: Jeśli
(liczymy
Jeśli rozwiązania istnieją, to dokończenie ich obliczania wymaga jeszcze
Należy znaleźć przecięcie promienia z trójkątem (lub ogólniej, z płaskim wielokątem). Aby znaleźć punkt wspólny promienia z płaszczyzną trójkąta, wystarczy rozwiązać układ równań liniowych, ale znacznie trudniejszym problemem jest rozstrzygnięcie, czy punkt wspólny promienia i płaszczyzny należy do trójkąta.
Dla trójkąta można użyć następującego algorytmu. W pierwszym kroku
dokonujemy takiej zmiany układu współrzędnych, aby promień pokrywał się
z dodatnią lub ujemną półosią
W drugim kroku rozwiązujemy układ równań z macierzą utworzoną ze współrzędnych w nowym układzie wierzchołków trójkąta:
W wyniku otrzymujemy współrzędne barycentryczne
Punkt przecięcia w przestrzeni możemy obliczyć ze wzoru
Współrzędne barycentryczne możemy wykorzystać do cieniowania (np. metodą Phonga) lub do obliczenia współrzędnych tekstury nakładanej na trójkąt.
Aby obliczyć przecięcie promienia z dowolnym wielokątem płaskim, możemy w podobny sposób sprowadzić zadanie do problemu dwuwymiarowego. Ze względów praktycznych (m.in. dla wygody cieniowania) wielokąty dowolne warto zastąpić odpowiednimi trójkątami przed przystąpieniem do śledzenia promieni i skorzystać z procedury dla trójkątów.
Jedną z największych zalet śledzenia promieni jest możliwość
,,dorabiania” obsługi nietypowych obiektów.
Możemy określić ,,rurkę Béziera”; jest to powierzchnia składająca
się z punktów położonych w danej odległości
Krzywa stanowiąca ,,oś” rurki jest stopnia
Jest to równanie algebraiczne stopnia
Aby rozwiązać pierwszy problem wystarczy przedstawić krzywą
Obliczenie punktu przecięcia i wektora normalnego polega na drobnym
oszustwie. Mając rozwiązanie
Obliczanie przecięć ma na celu znalezienie punktów przecięcia promienia z obiektem, albo stwierdzenie, że ich nie ma. O ile to pierwsze może wymagać dość kosztownych obliczeń, których nie da się uprościć, istnieje szybki test, który pozwala wykryć większość par promień/obiekt, które nie mają punktów wspólnych. Polega on na wprowadzeniu brył otaczających każdy obiekt w scenie. Jeśli obiekt jest powierzchnią algebraiczną lub bryłą wielościenną, rozwiązywanie równań, prowadzące do stwierdzenia, że rozwiązań nie ma, zajmuje zwykle dość sporo czasu (zależnie od stopnia powierzchni lub liczby ścian). Jeśli dla takiego obiektu wskażemy kulę, wewnątrz której ten obiekt jest zawarty, to możemy najpierw sprawdzić, czy promień przecina się ze sferą — brzegiem kuli i wykonywać dalsze, bardziej kosztowne obliczenia tylko w przypadku uzyskania odpowiedzi twierdzącej.
Można wprowadzać inne bryły otaczające, np. kostki (tj. prostopadłościany o ścianach równoległych do płaszczyzn układu), albo
elipsoidy (przydatne wtedy, gdy obiekt ma wydłużony kształt). Aby
dowiedzieć się, czy promień przecina prostopadłościan, możemy
zastosować algorytm Lianga-Barsky'ego (opisany
w p. 3.1.3). Poniżej jest przykład realizacji tego
algorytmu w zastosowaniu do tego testu. Promień jest reprezentowany przez
punkt początkowy
function TestBoxRay ( |
var |
function Test ( |
… Ta funkcja jest identyczna jak na str. 3.1.3 |
end {Test}; |
begin {TestBoxRay} |
|
if Test ( |
if Test ( |
if Test ( |
if Test ( |
if Test ( |
if Test ( |
return true; |
return false |
end {TestBoxRay}; |
Wprowadzenie bryły otaczającej dla każdego obiektu zmniejsza średni koszt wyznaczania przecięć (jeśli promienie są rozłączne z większością obiektów), ale nie obniża złożoności obliczeniowej algorytmu, bo nadal trzeba przetworzyć tyle samo par promień/obiekt. Można jednak wprowadzić hierarchię obiektów, której reprezentacja ma postać drzewa; korzeniem drzewa jest cała scena, a poddrzewa opisują zbiory obiektów znajdujących się blisko siebie. W każdym wierzchołku tworzymy reprezentację bryły otaczającej wszystkie obiekty reprezentowane przez ten wierzchołek i jego poddrzewa. Podczas śledzenia promieni przeszukujemy drzewo hierarchii sceny metodą DFS, pomijając każde poddrzewo, z którego bryłą otaczającą promień jest rozłączny.
Przykładowa scena przedstawiona na rysunku 7.5 została
opisana w postaci hierarchicznej — sąsiednie obiekty (kule i walce)
były łączone w pary, pary w czwórki itd., czyli drzewo wprowadzonej
hierarchii było binarne. Dla każdego wierzchołka drzewa (oprócz liści)
została znaleziona kostka otaczająca. Utworzenie obrazu w rozdzielczości
Jeśli nie ma ,,gotowej” hierarchii sceny, jest tylko lista obiektów, z których scena się składa, to można taką hierarchię wprowadzić ,,sztucznie”. Praktyczny sposób polega na znalezieniu bryły otaczającej (np. prostopadłościanu) dla każdego obiektu, a następnie na zbudowaniu drzewa binarnego, metodą łączenia wierzchołków w pary. Obiekty geometryczne, z których składa się scena, zostają liścmi drzewa. Dla każdego (nowego, wewnętrznego) wierzchołka znajdujemy bryłę otaczającą sumę obiektów w poddrzewach. Dwa wierzchołki do połączenia wybieramy tak, aby otrzymać nowy wierzchołek, którego bryła otaczająca jest najmniejsza (np. ma najmniejszą średnicę; to jest algorytm zachłanny, który może nie dać optymalnego drzewa, ale jest stosunkowo prosty i skuteczny). W tym celu można użyć kolejki priorytetowej, np. w postaci kopca. Dla scen złożonych z dużej liczby obiektów takie postępowanie jest dość kosztowne, ale jest ono opłacalne dzięki oszczędności czasu podczas właściwego śledzenia promieni.
Niezależnie od hierarchii sceny, wynikającej ze sposobu jej modelowania, można zmniejszyć złożoność obliczeniową śledzenia promieni za pomocą drzewa ósemkowego, które wprowadza hierarchię wynikającą z rozmieszczenia poszczególnych obiektów w przestrzeni. Drzewo należy utworzyć przed przystąpieniem do śledzenia promieni, dokonując adaptacyjnego rekurencyjnego podziału kostki zawierającej scenę. Adaptacja ta ma na celu skojarzenie z każdym węzłem drzewa możliwie krótkiej listy obiektów, które mają niepuste przecięcie z boksem reprezentowanym przez ten węzeł. Trudność, którą trzeba przy tym pokonać polega na tym, że należy unikać powielania wskaźników do tego samego obiektu w wielu takich listach.
Reguły adaptacyjnego podziału są następujące: kostkę dzielimy na mniejsze, jeśli istnieje obiekt, który
jest zawarty w jednej z kostek, które powstałyby z podziału kostki danej, lub
ma średnicę istotnie mniejszą (np.
Można arbitralnie ograniczyć wysokość drzewa (tj. głębokość podziału), a ponadto nie dzielić kostki wtedy, gdy nie spowoduje to otrzymania istotnie krótszych list obiektów.
Mając zbudowane drzewo można przystąpić do śledzenia promieni. Dla
ustalonego promienia wybieramy pewien punkt
Ponieważ pewne obiekty mogą być obecne w listach obiektów więcej niż
jednej kostki, więc warto zapobiec wykonywaniu pełnej procedury
wyznaczania przecięć danego promienia z tym samym obiektem, jeśli
występuje on w liście po raz drugi. Skuteczny sposób jest następujący:
opis obiektu występuje ,,w jednym egzemplarzu”, a element listy
w kostce składa się ze wskaźnika do tego opisu i wskaźnika do następnego
elementu. W opisie obiektu występuje pomocniczy atrybut, będący liczbą
całkowitą, o początkowej wartości
Duże puste obszary są reprezentowane przez stosunkowo duże puste kostki. Stosując drzewa ósemkowe, najwięcej czasu zużywa się na wyznaczanie sąsiada, tj. najmniejszej kostki, której ściana przylega do ściany kostki bieżącej i do której promień ,,wchodzi”. Przeszukiwanie drzewa można zacząć
od korzenia — wtedy czas znajdowania sąsiada jest proporcjonalny do poziomu w drzewie poszukiwanej kostki, albo
od kostki bieżącej (idziemy w górę, a następnie w dół) — wtedy czas zależy od poziomu ,,najmniejszego wspólnego przodka” kostki bieżącej i sąsiada.
Czas znajdowania sąsiada można zmniejszyć, jeśli zamiast drzewa
ósemkowego zastosujemy równomierny podział kostki otaczającej
scenę. W metodzie tej każdy bok kostki dzieli się na
zbyt gruby podział może być nieskuteczny (tj. listy obiektów są zbyt długie),
zbyt drobny podział powoduje, że większość elementów tablicy zawiera wskaźniki puste (czyli pamięć jest marnowana) i tablica zajmuje dużo miejsca,
duże puste obszary są drobno ,,poszatkowane” i czas przechodzenia przez taki obszar jest długotrwały,
duże obiekty występują w dużej liczbie list.
W praktyce przyjmuje się
Większość obiektów w typowych scenach jest matowa, w związku z czym nie
obserwujemy w takich scenach wielokrotnych odbić światła i nawet
zastosowanie algorytmu z
Narysuj scenę za pomocą algorytmu z
Kolejno dla każdego piksela na obrazie, odczytaj jego kolor —
określa on numer obiektu widocznego w tym pikselu. Z
Następnie wykonaj śledzenie promieni wtórnych. Jeśli obiekt jest matowy, to wystarczy zbadać, czy dany punkt jest w cieniu. Jeśli obiekt jest zwierciadlany lub przezroczysty, to rekurencyjne śledzenie promieni jest potrzebne w celu otrzymania obrazu obiektów odbitych lub położonych za tym obiektem.
Metoda śledzenia promieni może być zastosowana do otrzymania obrazu sceny złożonej z brył CSG, bez wyznaczania jawnej reprezentacji takiej bryły. Wystarczy, aby mając dany promień, wyznaczyć punkt przecięcia (i wektor normalny w tym punkcie) powierzchni prymitywu, która jest brzegiem bryły CSG.
Rozważmy dwie metody. Metoda pierwsza: Wyznaczamy punkty przecięcia promienia z wszystkimi prymitywami bryły CSG i porządkujemy je w kolejności rosnącej odległości od początku promienia. Dla każdego prymitywu jego przecięcie z promieniem składa się z odcinków (dla brył wypukłych jest to najwyżej jeden odcinek). Następnie wykonujemy operacje CSG (tj. regularyzowane działania teoriomnogościowe) na tych odcinkach, co jest bez porównania łatwiejsze niż działania na bryłach trójwymiarowych. Na końcu wystarczy wybrać koniec odcinka najbliżej obserwatora.
Metodę tę można usprawnić; wykonując działania na listach odcinków, jeśli jeden z argumentów różnicy lub przecięcia jest zbiorem pustym, to nie trzeba wyznaczać drugiego argumentu.
Metoda druga: W metodzie pierwszej trzeba wyznaczyć wszystkie punkty przecięcia promienia z wszystkimi prymitywami. Metoda druga opiera się na fakcie, że stosując drzewo ósemkowe (albo równomierny podział kostki), otrzymujemy poszczególne punkty przecięcia promienia i powierzchni obiektów w kolejności zbliżonej do uporządkowania ich wzdłuż promienia. Rozważmy drzewo CSG, w którego liściach umieścimy zamiast prymitywów ich części wspólne z promieniem (tj. sumy odcinków leżących na promieniu). Początkowo wszystkie liście drzewa oznaczamy jako ,,nieznane”. Po wyznaczeniu przecięcia promienia z dowolnym prymitywem, podstawiamy odpowiednie odcinki do drzewa CSG i próbujemy określić wyrażenia, których to są argumenty. Jeśli uda się dojść w ten sposób do korzenia, to znajdziemy w nim punkt najbliżej początku promienia, jak poprzednio.
Zjawisko intermodulacji (ang. alias) jest skutkiem reprezentowania sygnału (w tym przypadku obrazu) za pomocą skończonej liczby próbek. Objawia się ono w postaci
,,ząbkowanych” krawędzi obiektów na obrazie,
znikania lub zniekształcania małych przedmiotów,
zniekształcenia wyglądu tekstur (to jest najbardziej widoczny i najtrudniejszy do przeciwdziałania artefakt),
skokowego ruchu i efektów stroboskopowych w animacji.
Dokładniejszy opis zjawiska intermodulacji i metod radzenia sobie z nim będzie później, a na razie zajmiemy się metodami związanymi ze śledzeniem promieni.
Nadpróbkowanie (ang. supersampling). Wykonujemy
obraz o
Nadpróbkowanie adaptacyjne. Widoczne na obrazie artefakty zajmują zwykle nie więcej niż pewną małą część powierzchni obrazu (chyba, że dotyczą tekstury). Dlatego często robi się tak:
Wykonujemy obraz w niskiej rozdzielczości (jeden promień pierwotny na piksel),
Kolejno dla każdego piksela sprawdzamy, czy jego barwa różni się od barw sąsiednich pikseli o więcej niż określony próg. Jeśli tak, to generujemy dodatkowe promienie pierwotne (dla pewnej liczby podpikseli danego piksela) i obliczamy ostateczną barwę jako średnią barw podpikseli. Postępowanie to bywa czasem stosowane rekurencyjnie (tj. jeśli barwy podpikseli za bardzo się różnią, to podpiksele te podlegają dalszemu podziałowi i śledzi się jeszcze więcej promieni pierwotnych).
W pewnych sytuacjach nadpróbkowanie adaptacyjne może nie wykryć miejsc, w których należałoby śledzić dodatkowe promienie pierwotne. Często np. szczegóły wyglądu tekstury mogą być mniejsze niż piksel. Nie ma prostego rozwiązania tego problemu, zwłaszcza w przypadku obrazów, w których są widoczne odbicia obiektów w powierzchniach zakrzywionych.
Jittering. W przypadku nadpróbkowania artefakty w postaci ,, ząbkowanych” krawędzi obiektów są zastępowane przez mniej widoczne artefakty w postaci brzegu ostrego/nieostrego (okresowo na przemian). Lepsze efekty można osiągnąć zaburzając punkty, które określają kierunki promieni pierwotnych. Zamiast przez środek podpiksela, promień pierwotny jest określony przez wylosowany punkt należący do podpiksela. Takie postępowanie wprowadza do obrazu szum, który dla ludzkich oczu jest znacznie mniej widoczny i denerwujący.
Filtrowanie. Oprócz obliczania barwy jako średniej arytmetycznej próbek, można obliczyć średnią ważoną. Średnia taka jest przybliżeniem pewnej całki, która opisuje splot funkcji opisującej obraz z ustaloną funkcją zwaną filtrem. Funkcja taka jest dobierana zależnie od specyfiki urządzenia wyjściowego, np. może być inna dla monitorów z kineskopem i z wyświetlaczem ciekłokrystalicznym. W ogólności mamy dwa wzory; pierwszy opisuje to, co chcemy uzyskać:
a drugi realizację (zamiast całki obliczamy kwadraturę): | ||||
Filtr powinien być funkcją symetryczną, tj. spełniać warunki
unormowaną (tj.
Na przykład nadpróbkowanie i obliczanie średniej arytmetycznej jest zastosowaniem
filtru prostokątnego. Inne, często stosowane filtry to filtr stożkowy,
Gaussowski i inne. Szczególnie interesujący teoretycznie, choć
rzadko stosowany w praktyce jest filtr opisany przez funkcję sinc (łac. sinus cardinalis),
Wyświetlanie ciągu obrazów przedstawiających kolejne fazy ruchu daje złudzenie ruchu, co znalazło praktyczne zastosowania co najmniej od czasów braci Lumière.
Zasada działania kamery filmowej jest następująca.
Migawka jest tarczą z wyciętym pewnym segmentem i podczas filmowania
obraca się ze stałą prędkością. W czasie, gdy dowolna część lub
całe okienko o wymiarach klatki jest odsłonięte, film jest nieruchomy (i
następuje naświetlenie klatki). W czasie, gdy okienko jest zasłonięte,
następuje przesuwanie taśmy. Typowy kąt wyciętego segmentu migawki ma od
Dodatkowy skutek aliasu czasowego to tzw. zjawisko stroboskopowe. Jeśli mamy obiekt obracający się z dużą prędkością (np. śmigło, szprychy koła w dyliżansie), to możemy otrzymać wrażenie ruchu z inną (znacznie mniejszą) prędkością, być może w przeciwną stronę.
Aby otrzymać na klatkach produkowanego przez komputer filmu rozmyte
w kierunku ruchu obrazy obiektów, można dokonać nadpróbkowania i nieraz
tak się robi podczas stosowania algorytmu z
Aby zmniejszyć koszt obliczeń, można stosować techniki
przyśpieszające, takie jak drzewo ósemkowe. W takiej sytuacji bryła
ograniczająca obiekt musi być otoczką wszystkich położeń obiektu w
pewnym przedziale czasowym (który zawiera chwile
Oglądając scenę trójwymiarową, widz skupia uwagę na głównym przedmiocie swojego zainteresowania, nie zwracając uwagi na jego otoczenie i tło. Oko dostosowuje się do odległości od tego przedmiotu, wskutek czego bliższe i dalsze przedmioty są nieostre. Wykonując fotografię, trzeba również odpowiednio nastawić ostrość i nie jest to tylko kwestia niedoskonałości zasady działania obiektywu, ale przede wszystkim świadomego wyboru tematu zdjęcia. Obrazy, na których wszystko byłoby idealnie ostre, są trudniejsze w oglądaniu (i sprawiają nienaturalne wrażenie).
Obraz punktu utworzony przez obiektyw jest plamką o pewnej średnicy, która zależy od długości ogniskowej obiektywu, jego odległości od obiektu i od błony filmowej (albo macierzy CCD) oraz średnicy otworu przysłony. Inne czynniki, które mają na to wpływ (np. dokładne ustawienie soczewek, zjawiska związane z dyfrakcją) pominiemy, przedstawiając obiektyw jako idealną soczewkę, która spełnia równanie
W równaniu tym
Mamy dwa sposoby otrzymania obrazu, który charakteryzowałby się głębią
ostrości. Sposób pierwszy polega na postprocesingu; dla każdego piksela
musimy znać odległość punktu powierzchni widocznej w tym pikselu od
obserwatora (przypominam, że położenie obserwatora jest w tym przypadku
tożsame ze środkiem soczewki). Informację taką możemy uzyskać zarówno
jako wynik śledzenia promienia pierwotnego, jak i sięgając do
Metoda druga polega na zaburzaniu położenia obserwatora i ,,klatki”,
tj. prostokąta położonego na rzutni, na którym powstaje obraz.
Przypuśćmy, że chcemy ostrość ustawić na odległość
Rozważmy teraz punkt położony w odległości
Ponieważ przesunięcie
więc możemy je obliczyć następująco:
Uwaga: Rozpatrując punkt położony w innej odległości niż
Przed wykonaniem obrazu ustalamy parametry obiektywu i odległość ostrego
widzenia i na ich podstawie obliczamy maksymalne przesunięcie
Antyaliasing przestrzenny i czasowy oraz symulacja głębi ostrości są
możliwe do osiągnięcia także na obrazach otrzymanych za pomocą
Efekty specjalne, takie jak dym, chmury, płomienie itd. można wymodelować za pomocą układu cząsteczek (ang. particle systems). Często wiąże się to z animacją.
Cząsteczka jest obiektem, który w najprostszym przypadku ma tylko
Określamy pole wektorowe, które opisuje prędkości unoszenia cząsteczek przez wiatr, ,,cug” z komina itp. W zasadzie takie pole spełnia pewien układ równań różniczkowych cząstkowych, ale często wystarczy wygenerować je ,,ręcznie”.
W określonym miejscu (np. wylocie z komina) losujemy położenia początkowe cząsteczek, z określoną szybkością (np. kilkadziesiąt na jedną klatkę filmu).
Dalsze położenia cząsteczek obliczamy całkując pole wektorowe unoszenia. Dokładniej, następne położenie cząsteczki otrzymamy, dodając do poprzedniego położenia wektor prędkości unoszenia w tym miejscu razy przyrost czasu (odległość w czasie między wyświetlaniem kolejnych klatek) i przemieszczenie opisujące indywidualny ruch (ruchy Browna, opadanie z powodu grawitacji itd.).
Cząsteczki, które zostały uniesione poza ustalony obszar ,, znikają”. Zwalniamy zajmowane przez nie miejsca w tablicy cząsteczek i możemy w to miejsce wpisać położenia nowych cząsteczek, wylosowane w późniejszych chwilach.
Wykonujemy śledzenie promieni. Ponieważ średnica cząsteczek jest
równa
Zauważmy, że postępowanie to dla promieni wtórnych pozwala otrzymać obraz cienia rzucanego przez dym na inne przedmioty.
Aby uzyskać zadowalający efekt, zwykle wystarczy symulować ruch od
Program wykonujący obrazy metodą śledzenia promieni11Moje próby zwięzłego spolszczenia określenia “ray tracer” zakończyły się po tym, jak pomyślałem o ,,śledziu promieni”. Mimo poprawności rybnej konotacji (słowo ray oznacza po angielsku również płaszczkę) nie uważam tego pomysłu za udany i więcej prób nie podejmę. może (i powinien) składać się z modułów w znacznym stopniu niezależnych od siebie. Moduły te to
Translator reprezentacji sceny. W pakietach ,,użytkowych” moduł ten zawiera procesor tekstu, którego zadaniem jest utworzenie wewnętrznej reprezentacji sceny na podstawie skryptu (dostarczonego przez użytkownika programu). Procesor ten wywołuje procedury konstruujące obiekty reprezentujące poszczególne prymitywy i wierzchołki drzewa lub grafu hierarchii sceny (w tym np. wierzchołki reprezentujące operacje CSG) i buduje ten graf. Ponadto rozpoznaje i odpowiednio przetwarza opisy źródeł światła i położenia obserwatora.
Przed napisaniem translatora należy określić język opisu sceny, tj. pewien język formalny, którego zdaniami są dopuszczalne teksty skryptów. Translator składa się z analizatora leksykalnego (który może być wyposażony w makrogenerator), analizatora syntaktycznego (który rozpoznaje opisy obiektów i np. kojarzy rozpoznane opisy tekstur z rozpoznanymi opisami figur geometrycznych) i generatora obiektów, który tworzy obiekty, nadaje wartości ich atrybutom i buduje z nich drzewo lub graf hierarchii.
Możliwym rozwiązaniem zastępczym jest użycie w charakterze takiego translatora kompilatora języka programowania, w którym realizujemy cały program (np. Pascala, C, C++). Wtedy zamiast skryptu opisującego scenę użytkownik będzie musiał napisać i dołączyć do programu procedurę, która wywołuje (dostępne w postaci biblioteki) odpowiednie procedury konstruujące ,,wewnętrzną” reprezentację sceny. Po wywołaniu tej procedury program może przystąpić do syntezy obrazu.
Zaletą tego rozwiązania jest możliwość wykorzystania dowolnych konstrukcji językowych w celu utworzenia sceny, a także łatwość rozszerzania możliwości programu (np. dodawania nowych rodzajów prymitywów) bez potrzeby zmieniania języka skryptów. Wadą jest przyjęcie założenia, że użytkownik programu umie pisać przynajmniej proste programy i umie obsługiwać kompilator. W praktyce często kompilator pełni rolę translatora reprezentacji sceny podczas uruchamiania modułu syntezy obrazu. Są również gotowe pakiety, które oferują (czasem opcjonalnie) taki interfejs użytkownika.
Biblioteka obiektów. Każdy element reprezentacji sceny (np. prymityw lub obiekt złożony) jest obiektem, który powinien udostępniać metody stanowiące interfejs sceny z procedurą śledzenia promieni opisaną dalej. W najprostszym przypadku wystarczą dwie metody. Pierwsza z nich wyznacza punkty przecięcia promienia danego jako parametr z obiektem i wektory normalne powierzchni obiektu w tych punktach. Druga metoda dla ustalonego punktu oblicza wartość tekstury w tym punkcie, czyli parametry (związane z powierzchnią) występujące na przykład w modelu oświetlenia Phonga. Może też być trzecia metoda, której zadaniem jest narysowanie obiektu przy użyciu algorytmu z buforem głębokości, w celu przyspieszenia przetwarzania promieni pierwotnych sposobem opisanym w p. 11.3.3.
Bardzo wygodne jest zrealizowanie tych obiektów w języku ,,obiektowym”, na przykład w C++. Wspomniane metody będą oczywiście wirtualne. W klasie ,,figura” (której obiektami są wszystkie elementy reprezentacji sceny) metody będą puste, natomiast w podklasach będą odpowiednio przedefiniowane. Dzięki temu procedura śledzenia promieni może wywoływać odpowiednią metodę ,,nie wiedząc”, czy należy ona do obiektu opisującego sferę, płat B-sklejany, czy też wewnętrzny wierzchołek drzewa CSG. W ostatnim przypadku obiekt zawiera wskaźniki do poddrzew reprezentujących argumenty operacji CSG; metoda obiektu wywoła metody znajdowania przecięć promienia z tymi argumentami (,,nie wiedząc” jakiego one są rodzaju), a następnie obliczy punkt przecięcia promienia z bryłą CSG na podstawie wyników obliczeń dokonanych przez metody argumentów.
Procedura śledzenia promieni. Procedura ta otrzymuje promień jako argument. Jej zadaniem jest znalezienie odpowiedniego punktu przecięcia z którymś z obiektów (w tym celu procedura wywołuje metody obiektów), a następnie wygenerowanie promieni wtórnych, prześledzenie ich (za pomocą rekurencyjnego wywołania) i obliczenie światła niesionego przez promień do jego początku.
Jedynie ta procedura realizuje określony algorytm śledzenia, tj. tylko w niej jest określona liczba generowanych promieni wtórnych i kryterium zatrzymania rekurencyjnych wywołań.
Procedura śledzenia promieni może posługiwać się strukturą danych taką jak drzewo ósemkowe w celu usprawnienia obliczeń. Alternatywnie, zadanie zmniejszania złożoności obliczeniowej wyznaczania przecięć może spoczywać na metodach obiektów, jeśli obiekty te są zorganizowanie hierarchicznie. Na przykład procedura wywołuje metody tylko jednego lub najwyżej kilku obiektów, z których każdy jest korzeniem drzewa opisującego pewną część sceny. Działanie metody znajdowania przecięć promienia z obiektem zaczyna się od sprawdzania położenia promienia względem bryły otaczającej (i najczęściej na tym się kończy).
Generator promieni pierwotnych. To jest procedura, która oblicza kolor kolejnych pikseli na obrazie (wywołując procedurę śledzenia promieni), przy czym szczegóły obliczeń takie jak liczba promieni pierwotnych na piksel i rodzaj zastosowanego filtru w antyaliasingu są poza tą procedurą niewidoczne (z jednym wyjątkiem — w antyaliasingu czasowym procedura ta musi nadawać odpowiednie wartości globalnemu parametrowi czasu, na podstawie którego metody obiektów określają położenie tych obiektów w chwili, w której trafia je promień).
Biblioteka procedur wyjściowych, których zadaniem jest utworzenie odpowiedniego pliku w ustalonym formacie lub wyświetlenie obrazu na ekranie. Zmiana formatu pliku wymaga dokonania zmian tylko w tym module.
Treść automatycznie generowana z plików źródłowych LaTeXa za pomocą oprogramowania wykorzystującego LaTeXML.
strona główna | webmaster | o portalu | pomoc
© Wydział Matematyki, Informatyki i Mechaniki UW, 2009-2010. Niniejsze materiały są udostępnione bezpłatnie na licencji Creative Commons Uznanie autorstwa-Użycie niekomercyjne-Bez utworów zależnych 3.0 Polska.
Projekt współfinansowany przez Unię Europejską w ramach Europejskiego Funduszu Społecznego.
Projekt współfinansowany przez Ministerstwo Nauki i Szkolnictwa Wyższego i przez Uniwersytet Warszawski.