20:00Temat wykladu:
C++: Wstęp do Raytracingu (by Gynvael, 17.08.06 ) @ wyklady.net
Komentarze: http://forum.wyklady.net/index.php?topic=77.0
20:09GynvaelWitam wszystkich na wykladzie o zacnym tytule 'Wstep do Raytracingu' ;>
GynvaelW sumie kto ja jestem mowilem juz na innych wykladach
GynvaelWiec w ramach wstepu powiem tylko ze wyklad dedykuje mojej ukochanej Arashi i Salvationowi ;>
20:10Gynvael(ktory siedzi kolo mnie i sie usmiecha ;>)
Gynvael(glupio usmiecha)
GynvaelDobra
GynvaelCo bedzie potrzebne:
Gynvael1) komputer + kompilator jezyka c++ (najlepiej z rodziny GCC)
20:11Gynvaelpod windowsem bedzie to MinGW GCC (mingw.org), pod linuxem standardowe linuxowe gcc ;>
Gynvael2) jako ze bedzie pare animacji, przyda sie player (polecam mplayer) ktory umie odtworzyc animacje .avi (DivX 4.X)
Gynvaelhttp://divx.pl/download.php?id=001001 - divx
20:13Gynvaelyh.. sponsorem wykladu jest Quit (Ping timeout) by TPSA
Gynvaelhttp://divx.pl/download.php?id=001001 - divx
Gynvaeltam mozna sciagnac odpowiedni kodek ;>
Gynvael3) troche wolnego czasu zeby to czytac ;>
GynvaelWszelkie pytania podczas wykladu prosze na priv ;>
GynvaelOK ;>
GynvaelNa dzisiejszym wykladzie (pierwszym z kilku) bedzie o:
Gynvael- co to jest Raytracing
20:14Gynvael- na czym on polega
Gynvael- jak napisac prosty engine raytracingowy w C++
Gynvaeloraz omowienie paru rzeczy takich jak oswietlenie, prymitywy, etc
Gynvael;>
GynvaelDobra.. jedziemy ;>
20:15GynvaelRaytracing jest to jedna z metod renderingu scen 3D
20:16GynvaelWymaga wiekszej ilosci obliczen niz niektore inne metody (np te znane z gier typu Doom 1 ;>)
Gynvaelale daje duzo ladniejsze rezultaty.
GynvaelDodam ze nie bedziemy mowic o Raytracingu w czasie rzeczywistym, a o raytracingu scen do bitmap po prostu ;>
20:17Gynvael<dragon> moze stworzyc kanal #wyklady-dyskusje ? moznaby gadac w trakcie wykladu ;>
GynvaelNa czym polega ta metoda ?
GynvaelPopatrzy na chwile na monitor
GynvaelTo co widzimy to zbior pixeli
Gynvaeljesli narysujemy np kolo, to na dobra sprawe bedzie ono tylko zbiorem pixeli
20:18Gynvael
Gynvaelkazdy pixel ma swoj kolor (RGB)
20:19Gynvaelczemu mowie o pixelach ? poniewaz raytracing jest metoda renderingu w ktora stara sie odpowiedziec na pytanie
Gynvaeljakiego koloru jest dany pixel
Gynvaelwyobrazmy sobie nasz ekran w przestrzeni 3D
Gynvaeljest to nie trudne raczej ;>
Gynvaelumiesmy przed ekranem miotacz promieni ("kamere")
20:20Gynvaeli wystrzelmy promien przez nasz ekran, przez kazdy konkretny pixel po kolei
Gynvaelzalozmy teraz ze za naszym ekranem sa jakies obiekty
Gynvaelnp jest jedna kula
Gynvael
Gynvaelekran jako prostokat
20:21Gynvaelnp prostokat o wymiarach (w pixelach) 640x480
Gynvaelna powyzszym obrazku jest rzut z boku (2D) na to o czym mowie
Gynvaelpo lewej jest kamera, jest ekran widziany z boku
Gynvaeli jest kula (obiekt, prymityw)
20:22GynvaelZauwazyc mozna nastepujace rzeczy
Gynvaelmianowicie: czesc promieni przelatuje gdzies obok kuli
Gynvaelale czesc w nia trafia
Gynvaeljesli promien w nic nie trafi
Gynvaelmozemy uznac ze trafil w tlo, czyli np czarny kolor
Gynvaela jesli w cos trafi, np w kule, to mozemy w danym pixelu (przez ktory promien przechodzi)
20:23Gynvaelumiescic np kolor kuli ;>
Gynvaelzyli czerwony
Gynvael*czyli
Gynvaelwidac tutaj zasadnicza roznice od tradycyjnej rasteryzacji 2D->3D uzytej np w w/w doom 1
20:24Gynvaelw tradycyjnej metodzie chodzi o odpowiedz na pytanie, "gdzie na ekranie lezy dany obiekt"
20:25Gynvaelnatomiast w raytracingu chodzi bardziej o odpowiedz "czy patrzac przez ten jeden dany pixel widzimy jakis obiekt"
Gynvaelok ;> tyle wstepu
Gynvaeljak wyglada przykladowa scena wyrenderowana przez raytracer ? np tak:
20:26Gynvael
Gynvael
Gynvael
20:27Gynvaelwyglada to ladnie.. ale jak cos takiego napisac
Gynvaeli czemu akurat w C++
Gynvael;>
Gynvaelw raytracingu operujemy sporo na wektorach, a C++ posiada sliczne przeciazenia operatorow, dzieki czemu niektore kawalki kodu zajmujace po 10 linii w C, beda zajmowac jedna linijke w C++
20:28Gynvaelco to jest wektor ?
Gynvaelw duzym skrocie, jest to 'odcinek' (pamietacie z matematyki co to ne?) zaczynajacy sie w punkcie 0,0 i konczacy gdziekolwiek (np 1, 2)
20:29Gynvael(jesli mowimy o 2D)
Gynvaelhttp://pl.wikipedia.org/wiki/Wektor
20:30Gynvaelwektor ma swoj kierunek (tj wskazuje pewien kierunek)
Gynvaelwektor mozna okreslic na dwa sposoby
Gynvael1) podajac jego koniec, np w przypadku 3D moze to byc [1,2,3]
Gynvael2) podajac kat od osi postrzegolnych i dlugosc wektora (ale to nam nie potrzebne)
Gynvaelna wektorach mozna wykonywac rozne operacje matematyczne
20:31Gynvaelnp wektory mozna dodawac
Gynvael
20:32Gynvaelmozna odracac je, mnozyc na dwa sposoby (iloczyn skalarny i wektorow)
Gynvaelkazdy wektor ma takze dlugosc
Gynvaeldlugosc liczy sie bardzo standardowym wzorem: sqrt( X*X + Y*Y + Z*Z ) w przypadku 3D, gdzie X,Y,Z to koordynaty wektora
Gynvaelmozna je rowniez normalizowac
20:33Gynvaelco to znaczy 'znormalizowac wektor' ?
Gynvaelchodzi tutaj o zmniejszenie dlugosci wektora do jednosci (1), przy jednoczesnym zachowaniu kierunku jaki wskazuje
Gynvaeluzyskuje to sie dzielac kazda wspolrzedna wektora (X Y Z) przez jego dlugosc ;>
Gynvaeletc
20:34GynvaelPierwsza rzecza ktora jest potrzebna przy silniku raytracingowym jest jakas polsensowna
Gynvaelimplementacja wektorow wlasnie ;>
Gynvaelhttp://wyklady.net/ray1/r1.zip
20:35GynvaelPod tym linkiem znajduja sie zrodla implementacji razem z prostym programem testujacym
Gynvaelrzucmy okiem na plik Vector3D.h
Gynvaelczyli interfejs wektorow 3D
GynvaelVector3D();
GynvaelVector3D(double x, double y, double z);
Gynvaeltworzac wektor mozna (ale nie trzeba) podac mu odrazu wspolzedne
20:36Gynvaelvoid PrintVector();
Gynvaeljest tam tez funkcja do wypisywania na konsoli pozycji wektora
GynvaelVector3D& operator= (Vector3D v);
GynvaelVector3D& operator-= (Vector3D v);
GynvaelVector3D& operator+= (Vector3D v);
GynvaelVector3D operator+ (Vector3D v);
GynvaelVector3D operator- (Vector3D v);
GynvaelVector3D Cross(Vector3D v);
Gynvaeldouble Dot(Vector3D v);
Gynvaeldouble Length();
Gynvaeldouble SqrLength();
Gynvaelvoid Norm();
Gynvaelzestaw operacji na wektorach
20:37Gynvaelodejmowanie, dodawanie, pobranie dlugosci, pobranie kwadratu dlugosci, normalizacja, dot i cross (czyli iloczyn skalarny i wektorowy)
GynvaelVector3D operator* (double r);
GynvaelVector3D& operator*= (double r);
Gynvaeljest tez operator ktory umozliwia pomnozenie wektora przez skalar (liczbe)
Gynvaelnp majac wektor
Gynvael[1,2,3]
Gynvaelchcemy go pomnozyc przez 5
Gynvael[1,2,3] * 5 == [5, 10, 15] ;>
20:38GynvaelVector3D operator* (Vector3D v);
GynvaelVector3D operator*= (Vector3D v);
Gynvaelto sa dwie dodatkowe funkcje
Gynvaelz wektorami nei majace w tym wypadku nic wspolnego
Gynvaelo nich za chwile
Gynvaelskompilujmy caly kod ktory tam jest
Gynvael(jak skompilowac ? jest w pliku vtest.c na gorze)
20:39Gynvael
20:39:13 >g++ Vector3D.cpp vtest.cpp -Wall -o vtest.exe
Gynvael
20:39:32 >vtest.exe
Gynvael
[1.000000, 4.000000, 9.000000]
Gynvael
20:39:35 >
20:40Gynvaelw vtest.c jest dosc prosty program
GynvaelVector3D a(1.0,2.0,3.0), b;
Gynvaelb = a * a;
Gynvaelb.PrintVector(); putchar('\n');
GynvaelOK ;>
Gynvaeljak dzialaja wektory dokladnie ? pozostawiam to wlasnej analizie ;>
Gynvael(jako ze nie jest to tematem tego wykladu)
20:41Gynvaelteraz taka mala dygresja
Gynvaeljak wspomnialem kazdy pixel ma kolor
Gynvaelzazwyczaj poslugujemy sie kolorami 24-bitowymi (lub 32)
Gynvaelkolor sklada sie z 3ch skladowych
GynvaelR - Red - Czerwona
GynvaelG - Green - Zielona
GynvaelB - Blue - Niebieska
Gynvaelna kazda skladowa przypada 8 bitow
20:42Gynvaelczyli przyjmuje ona wartosci od 0 do 255 (0 - 2^8-1)
Gynvaelwygodne jesli chodzi o ekran
Gynvaelale troche nie wygodne jesli chodzi o sama grafike
Gynvaela co jesli 'rozdzielczosc kolorow' 256 nam nie wystarcza ?
Gynvaelnp 1024 odcienie byly by lepsze etc
20:43Gynvaelwieksza 'rozdzielczosc' w czasie obliczen zapewnie lepsze efekty w koncowym obrazie
Gynvael(mimo iz sam koncowy obraz ma te 256 odcieni na barwe)
20:44Gynvaelw raytracingu bede korzystal z reprezentacji koloro nie (unsigned int) 0-255, a (double) 0.0 - 1.0
Gynvaelwszystkie wartosci ponizej 0.0 bede traktowal jak 0.0 przy konwersji 0.0-1.0 -> 0-255
Gynvaela wszystkie powyzej jako 1.0
20:45Gynvaelok.. co mozna robic z kolorami ?
Gynvaeldodawac je
Gynvaelodejmowac
Gynvaelmnozyc
Gynvaeletc etc
Gynvaelwiec przydalo by sie napisac klase ktora to obsluguje
Gynvaelale w8 w8.. Vector3D bardzo podobna funkcjonalnosc zapewnia
Gynvaelbrakuje tam tylko mnozenia kolorow
Gynvaeltj mnozenia kolorOUT = kolorA.R * kolorB.R etc
20:46Gynvaelkazdej barwy oddzielnie
GynvaelVector3D operator* (Vector3D v);
GynvaelVector3D operator*= (Vector3D v);
Gynvaelte dwa operatory wlasnie do tego sluza
Gynvaelnie sa to operacje na wektorach, ale na kolorach
Gynvaeljako ze przyjmu Vector3D operator* (Vector3D v);
GynvaelVector3D operator*= (Vector3D v);
Gynvaeleh sorx
Gynvaeljako ze uzywal bede Vector3D do kolorow, to oprocz oznaczen x,y,z
Gynvaelstruct { double x, y, z; };
Gynvaelstruct { double r, g, b; };
Gynvaelpojawily tam tez sie oznaczenia r, g, b ;>
20:47Gynvaeldobra
Gynvaelmamy wiec cos do wektorow i cos do kolorow
Gynvaelteraz by sie przydalo cos do trzymania efektu / koloru pixeli
Gynvaelczyli obsluga bitmap
Gynvaelnajlepiej z mozliwoscia zrzucania do pliku
Gynvaelhttp://wyklady.net/ray1/r2.zip
20:48GynvaelJest tam mala prosta klasa Image24, ktora dostarcza bardzo podstawowa obluge bitmap 24-bitowych
20:49Gynvaeloraz umozliwia zapisanie danej bitmapy jako TGA (czemu TGA ? bo to bardzo prosty format ;>)
Gynvaelprzy tworzeniu nowego obiektu Image24 podaje sie szerokosc i wysokosc bitmapy
Gynvaela potem po prostu modyfikuje sie wartosci w tablicy 'data'
20:50Gynvaeltablica data to tablice unsigned intow
Gynvaelkazdy pixel to jeden element w tej tablicy (ofc)
Gynvaelkolor pixeli sa tam zapisane tak: 0xRRGGBB ;>
Gynvaelvoid SaveAsTGA(const char *filename) const;
Gynvaelco robi ta funkcja latwo sie domyslic
Gynvaelpo skompiowaniu i uruchomieniu testowego programu (patrz plik itest.cpp)
20:51Gynvaeltworzy sie plik dump.tga ktory zawiera 'oczy zlego kaczora donalda', czy tam jakas funkcje trygonometryczna, jak kto woli ;>
Gynvael
20:52Gynvaeldobra.. mamy 3 rzeczy teraz
Gynvael1) wektory
Gynvael2) kolory
Gynvael3) bitmapu
Gynvaelwiec mozemy sie brac za sam silnik
20:53Gynvaelco powinien zawierac silnik na tym etapie ?
Gynvael1) liste prymitywow (obiektow)
Gynvael2) umozliwiac dodawanie obiektow do sceny
20:54Gynvael3) umozliwiac wyrenderowanie tej sceny
Gynvaeldodatkowo
Gynvaelkazdy rodzaj obiektu powinien zawierac funkcje
Gynvaelktora otrzyma promien (promien dla nas to bedzie punkt w przestrzeni skad zostal wystrzelony promien (kamera) oraz wektor kierunkowy (tj wektor pokazujacy kierunkek w ktorym leci promien))
20:55Gynvaeli powie czy promien TRAFIA w dany obiekt (tj sie z nim przecina
20:56Gynvaeljak powinien dzialac rendering
GynvaelDla kazdego pixela powinien byc wystrzelony promien z kamery
20:57GynvaelPo czym z listy obiektow musi zostac wybrany obiekt ktory lezy najblizej punktu wystrzelenia promienia (kamery) i sie przecina z promieniem
GynvaelI w naszym przypadku teraz
Gynvaelpowinien zostac zwrocony kolor czarny jesli promien nie trafil w zaden obiekt
20:58Gynvaellub bialy jesli trafil w jakis
Gynvaelhttp://wyklady.net/ray1/r3.zip
Gynvaelrzucmy okiem na ten projekt
20:59Gynvaelwidac tam pliki z r2 i r1 czyli Image24.* i Vector3D.*
Gynvaeloraz sporo nowych
Gynvaelkrotko o nich:
GynvaelPrimitive.* to deklaracja interfejsu prymitywow.. patrzac w Primitive.h dowiemy sie jakie sa wspolne cechy kazdego obiektu
21:00Gynvaelpoki co jedyna wspolna cecha obiektow jest to ze maja funkcje
Gynvaelint Intersect(Ray &ray, double &dist)
GynvaelIntersect (eng. przeciecie)
Gynvaelktora mowi czy promien przecina sie z obiektem
21:01Gynvael< SBKch> jak skompilowac to r3.zip?
Gynvaelnapisac 'make'
Gynvaellub w skrajnych przypadkach mingw32-make
Gynvaeldodam ze 'make test' uruchomi aplikacje
Gynvaelok
GynvaelPrimSphere.*
21:02Gynvaelto jest pierwszy i jedyny poki co rodzaj obiektu supportowany przez nasz engine
GynvaelSphere = sfera (pusta kula)
Gynvaelczemu kula ?
Gynvaelponiewaz matematycznie bardzo latwo jest sprawdzac przeciecie promienia z kula
21:03Gynvaelkula jest opisana przez pozycje w wirtualnym swiecie 3D naszej sceny (X,Y,Z) oraz przez promien
Gynvaelprzeciecie sprawdza sie po prostu poprzez sprawdznie czy prosta bedaca promieniem nie przechodzi dalej niz promien_kuli od punktu srodek_kuli ;>
21:04Gynvael...
Gynvael<@Gynvael> przeciecie sprawdza sie po prostu poprzez sprawdznie czy prosta bedaca promieniem nie przechodzi dalej niz promien_kuli od punktu srodek_kuli ;>
Gynvael<@Gynvael> (patrz odleglosc punktu od prostej)
21:05GynvaelRay.*
Gynvaeltam mamy malutka klase opisujaca promien
Gynvaeljak mowilem juz wczesniej promien to dla nas punkt wystrzelenia promienia i kierunkek w ktorym leci ;>
Gynvaelpublic:
GynvaelVector3D Origin, Direction;
GynvaelOrigin == zrodlo
GynvaelDirection == kierunek
GynvaelRTEngine.*
21:06Gynvaelto jest nasz Silnik
Gynvaelpoki co we wnetrzu silnika sa dwie rzeczy
Gynvaelstd::vector<Primitive*> PrimitiveList;
GynvaelVector3D Trace(Ray ray);
21:07Gynvaelpierwsze to lista obiektow o ktorej mowilem wczesniej
Gynvaela drugie to funkcja sledzaca jeden promien.. funkcja ta wywolywana jest dla KAZDEGO PIXELA ekranu i zwraca KOLOR pixela w tym miejscu
Gynvaelpoki co kolor to czarny - nie trafiono w obiekt
Gynvaelbialy - trafiono
Gynvaela co do interfejsu
Gynvaelvoid AddSphere(Vector3D Center, double Radius);
Gynvaelvoid Render(Image24 *img);
21:08Gynvaelto dwie funkcje sa
GynvaelAddSphere dodaje kule do sceny
Gynvaela Render renderuje scene do bitmapy
Gynvaelprzed odpaleniem zajrzyjmy jeszcze do test.cpp
Gynvaelto jest prosty programik testowy
21:09GynvaelImage24 Img(640, 480);
GynvaelRTEngine RT;
GynvaelRT.AddSphere(Vector3D(0.0,0.0,3.0), 1.0);
GynvaelRT.Render(&Img);
GynvaelImg.SaveAsTGA("dump.tga");
Gynvaelkod jest bardzo krotki
Gynvael1) tworzona jest bitmapa 640x480
Gynvael2) tworzony obiekt-engine
Gynvael3) dodawana jest jedna kula do sceny, na miejsce [0,0,3] o promieniu 1
Gynvael4) scena jest renderowana do bitmapy
21:10Gynvael5) i zapisywana w pliku dump.tga
Gynvaeldodam w tym miejscu ze kamere 'na sztywno' poki co umiescilem w miejscu 0,0,-5
Gynvaelnatomiast ekran lezy dla nad na plaszczyznie XY (Z = 0), w koordynatach (przypominam ze ekran to prostokat):
21:12Gynvaelco ostatnie doszlo ?
DJ_cool_21:10 <@Gynvael> natomiast ekran lezy dla nad na plaszczyznie XY (Z = 0), w koordynatach (przypominam ze ekran to prostokat):
21:13Gynvaellewy gorny rog: -2, 1.5, 0
Gynvaelprawy dolny: 2, -1.5, 0
Gynvaelthx DJ_cool_;>
DJ_cool_tak
DJ_cool_aw.
Gynvaelprosze tez jeszcze zauwazyc ze kula na scenie lezy bezposrednio przed kamera
Gynvaeltj mozna sie jej na srodku ekranu spodziewac
Gynvaelok ,kompilujemy i odpalamy
21:14Gynvael
21:14:05 >make test
Gynvael
g++ -c -o Image24.o Image24.cpp
Gynvael
g++ -c -o PrimSphere.o PrimSphere.cpp
Gynvael
g++ -c -o Ray.o Ray.cpp
Gynvael
g++ -c -o RTEngine.o RTEngine.cpp
Gynvael
g++ -c -o test.o test.cpp
Gynvael
g++ -c -o Vector3D.o Vector3D.cpp
Gynvael
g++ -c -o Primitive.o Primitive.cpp
Gynvael
g++ Image24.o PrimSphere.o Ray.o RTEngine.o test.o Vector3D.o Primitive.o -o rtt
Gynvael
est.exe
Gynvael
rttest.exe
Gynvael
21:14:19 >
Gynvaelutworzyl sie plik dump.tga
Gynvael
Gynvaeltak wyglada jego zawartosc
21:15Gynvaeljest kula na srodku, zgadza sie
Gynvaelprzyjrzyjmy sie blizej procedurze Render w silniku
GynvaelVector3D CameraPos(0.0, 0.0, -5.0);
Gynvaeljak nietrudno sie domyslic, jest to pozycja kamery ;>
Gynvaeldouble WX1 = -2.0, WX2 = 2.0, WY1 = 1.5, WY2 = -1.5;
21:16Gynvaelto natomiast sa koordynaty ekranu w wirtualnej przestrzeni naszej sceny (przed chwila o nich mowilem)
Gynvaeldouble DX = (WX2 - WX1) / (double)img->width;
Gynvaeldouble DY = (WY2 - WY1) / (double)img->height;
Gynvaeldouble SX = WX1, SY = WY1;
21:17Gynvaelprostokat ekranu jest podzielony na 640x480 pixeli
GynvaelDX to szerokosc pixela w wirtualnym swiecie (szerokosc ekranu / ilosc pixeli)
GynvaelDY to wysokosc pixela
21:24Gynvaelyh
Gynvaelna czym skonczylem?
21:25GynvaelDX to szerokosc pixela w wirtualnym swiecie (szerokosc ekranu / ilosc pixeli)
GynvaelDY to wysokosc pixela
GynvaelDX i DY sluza nam do wyznaczenia koordynatow kazdego pixela na ekranie
Gynvaelzmienne SX i SY to natomiast iteratory
Gynvaelsa one uzywane w petli
Gynvaeldo wytrzelenia (Trace) promienia przez kazdy pixel
21:26Gynvaelint x, y;
Gynvaelunsigned int *px = img->data;
Gynvaelx,y - kolejne iteratory
Gynvael*px natomiast wskazuje w bitmapie na pixel ktory aktualnie analizujemy
Gynvaelfor(y = 0; y < img->height; y++)
Gynvael{
GynvaelSX = WX1;
Gynvaelfor(x = 0; x < img->width; x++)
Gynvael{
Gynvael[...]
GynvaelSX += DX;
Gynvaelpx++;
Gynvael}
GynvaelSY += DY;
Gynvael}
21:27Gynvaelnastepnie jest petla, ktora w skrocie mozna okreslic jako 'Dla kazdego pixela z bitmapy...'
Gynvaelco sie dzieje w tej petli ?
GynvaelRay ray(CameraPos, Vector3D(SX, SY, 0.0));
Gynvaelray.Direction = ray.Direction - ray.Origin;
Gynvaelray.Direction.Norm();
Gynvaelpo pierwsze tworzony jest nowy promien, wyznaczany jego wektor kierunkowy
Gynvael(ten wektor jest tez normalizowany)
GynvaelVector3D color = this->Trace(ray);
21:28Gynvaelpo czym jest wystrzelany
Gynvaelfunkcja Trace zwraca kolor
Gynvaelint r, g, b;
Gynvaelr = (int)(color.r * 256.0);
Gynvaelg = (int)(color.g * 256.0);
Gynvaelb = (int)(color.b * 256.0);
Gynvaelr = r > 255 ? 255 : r < 0 ? 0 : r;
Gynvaelg = g > 255 ? 255 : g < 0 ? 0 : g;
Gynvaelb = b > 255 ? 255 : b < 0 ? 0 : b;
Gynvaelnastepnie ten kolor jest tlumaczony z 0.0 - 1.0 -> 0 - 255
Gynvael*px = (r << 16) | (g << 8) | (b);
21:29Gynvaelpo czym jest zapisywany do bitmapy
21:30Gynvaeldzialanie petli glownej jest proste
Gynvaelrzucmy okiem teraz na Trace
GynvaelVector3D color(0.0, 0.0, 0.0);
Gynvaelto jest zmienna do ktorej zapisujemy obliczony kolor
21:31Gynvaeljest ona na koncu zwracana
Gynvaeldouble dist = 1000000000.0f;
GynvaelPrimitive *prim = NULL;
Gynvaelte dwie zmienne pomoga nam znalezc obiekt z ktorym promien sie przecina (jesli sie przecina) i ktory jest najblizej zrodla promienia (kamery)
Gynvaelnastepnie jest petla
Gynvaelvector<Primitive*>::iterator iter;
Gynvaelfor(iter = this->PrimitiveList.begin(); iter != this->PrimitiveList.end(); iter++)
Gynvael{
Gynvaeldouble temp_dist;
Gynvaelif((*iter)->Intersect(ray, temp_dist) == 0)
Gynvaelcontinue;
Gynvaelif(temp_dist < dist)
Gynvael{
Gynvaelprim = *iter;
Gynvaeldist = temp_dist;
Gynvael}
21:32Gynvael}
Gynvaelpetla dziala w ten sposob:
GynvaelDla kazdego obiektu na scenie:
GynvaelSprawdz czy promien przecina sie z obiekitem. Jesli nie, nie rob nic.
21:33GynvaelJesli tak, sprawdz czy obiekt jest blizej kamery niz ten co poprzednio znalezlismy.
GynvaelJesli jest, to zapamietaj ten obiekt i jego odleglosc od kamery.
Gynvaelkamery == zrodla promienia
21:34Gynvaeljak widac uzywamy tutaj funkcji Intersect dla kazdego obiektu
Gynvaelfunkcja ta zwraca 0 jesli obiekt sie nie przecina z promieniem
Gynvael1 jesli sie przecina
Gynvaeli dodatkowo -1 jesli promien jest wewnatrz obiektu
Gynvaelz tego ostatniego narazie korzystac nie bedziemy ;>
21:35GynvaelIntersect zwraca rowniez odleglosc od zrodla promienia do miejsca przeciecia
Gynvael(dzieki temu wykonujac proste obliczenie zrodlo_promienia + kierunek_promienia * odleglosc bedziemy mogli uzyskac dokladne miejsce przeciecia)
21:36Gynvaelok.. po tej petli wiec mamy nastepujace informacje
Gynvael1) czy promien przecial sie z jakims obiektem
Gynvael2) jak daleko jest do tego obiektu
Gynvaelteraz mozemy wykonad jakis pixel shader, czyli jakies obliczenia ktore z roznych czynnikow wylicza kolor danego pixela
Gynvaelw tym przypadku jest to bardzo prosty shader
21:37Gynvaelif(prim)
Gynvaelcolor = Vector3D(1.0, 1.0, 1.0);
Gynvaelczyli 'Jesli sie z czyms przecielo, zwroc kolor BIALY'
21:38Gynvaeldobra ;>
Gynvaelmamy sliczna scene, czarno biala ;p
Gynvaelzrobmy troche bardziej zaawansowany shader
21:39Gynvaelmianowicie wyliczmy kolor na podstawie odleglosci miejsca przeciecia od zrodla promienia
Gynvaelodleglosc mamy
Gynvaelwystarczy cos tam ja podzielic etc i mamy juz kolor
Gynvaelhttp://wyklady.net/ray1/r4.zip
Gynvaelrzucmy okiem na ten kod
Gynvaelna poczatek skompilujmy go i odpalmy
Gynvaelstandardowe make test
Gynvaelwygenerowany zostanie pliczek dump.tga
21:40Gynvaeldodam ze do test.cpp dodalem tutaj jeszcze 2 kulki
Gynvaeltak ze na scenie teraz mamy 3
21:41GynvaelRT.AddSphere(Vector3D(1.0,0.0,0.4), 0.4);
GynvaelRT.AddSphere(Vector3D(0.0,0.0,0.5), 0.4);
GynvaelRT.AddSphere(Vector3D(-1.0,0.0,0.6), 0.4);
Gynvaelzwroccie uwage ze ta najbardziej po lewej jest najblizej ekranu
Gynvaela ta po prawej najdalej
Gynvaelod ekranu
Gynvaele odwrotnie ;p
21:42Gynvael
Gynvaeljak widac kulki zostaly ladnie 'pocieniowane'
Gynvaeldo czego taki shader (troche pomodyfikowany jeszcze) mogl by sluzyc ? np do efektu mgly ;>
Gynvaelale narazie sie tym nie zajmujmy
Gynvaelrzucmy okiem jeszcze na animacje kulki poruszajacej sie po ekranie
21:43Gynvaelhttp://wyklady.net/ray1/dist_shader.avi
Gynvaelprzypominam ze DivX 4.XX do tego jest potrzebny
Gynvaelanimacja zajmuje ponizej 100kb
21:44Gynvaelwidac na niej shader ktory teraz wybralismy w akcji ;>
Gynvaelok
Gynvaelwszystko ladnie
Gynvaelale troche ubogo
Gynvaelzostawmy narazie w spokoju ten shaderek zalezny od odleglosci
21:45Gynvaeli dorzucmy do engine'u pare istotnych rzeczy
Gynvaelmianowicie kazdy obiekt ma jakis material
Gynvaelco to jest material ?
21:46Gynvaeljest to zbior cech (takich jak np kolor, odbijalonosc swiatla etc) ktore opisuja dany obiekt
Gynvaelnp mozemy powiedziec ze jakas tam kulka jest zielona i matowa
Gynvaela inna jest niebieska i wypolerowana
Gynvaeltakie cechy wlasnie zapisuje sie w materiale
Gynvaelwprowadzmy takze swiatla
21:47Gynvaelswiatlo dla nas poki co bedzie to PUNKT w przestrzeni, ktory emanuje swiatlo w danym kolorze
Gynvaelczyli swiatlo dla nas == punkt + kolor ;>
21:48Gynvaelteraz omowmy pare rodzajow oddzialywania swiatla na obiekt na scenie
Gynvaelmamy cos takiego jak:
Gynvael(w naszym przypadku, bo rodzajow swiatel jest wiecej)
Gynvaelswiatlo rozproszone - diffusive
21:49Gynvaelswiatlo refleksyjne - specular - rekleksy/blyski na obiektach powstaja gdy obiekt ma wysokie specular
GynvaelDiffusive i Specular
Gynvaelto sa cechy materialu
Gynvaelprzykladowo
Gynvaeljesli obiekt jest matowy
21:50Gynvaelto bedzie mial zerowe Specular (nie beda sie na tym materiale odblyski tworzyc ani refleksy) i Diffusive w granicach np 40%
Gynvaela gdy mamy w rece np wypolerowany przez jubilera kamien, to on moze miec wysoki Specular (np 40% to sporo) i Diffusive w granicach 30%
Gynvaelza chwile wyjdzie to w praniu
Gynvael;>
21:51Gynvaelok
Gynvaela teraz troche kodu
Gynvaelhttp://wyklady.net/ray1/r5.zip
Gynvaelrzucmy okiem na poczatku na test.cpp
Gynvaelpotem skompilujemy
Gynvaela potem omowie nowy shader ktory tu uzylem
21:52Gynvaelok
GynvaelMaterial PolishedStone(Vector3D(0.0, 1.0, 0.0), 0.3, 0.4);
GynvaelMaterial Paper(Vector3D(1.0, 1.0, 0.8), 0.0, 0.5);
Gynvaelna poczatek tworze dwa materialy
Gynvaelmaterial przyjmuje 3 argumenty
GynvaelMaterial(Vector3D Color, double Specular, double Diffusive);
21:53GynvaelKolor, wspolczynnik odbijalnosci swiatla i wspolczynnik rozproszenia swiatla ;>
GynvaelPolishedStone - wypolerowany kamien - kolor zielony (0,1,0), 30% odbijalnosci (0.3), 40% rozproszenia (0.4)
21:54GynvaelPaper - papier - kolor kremowy (1,1,0.8), matowy (0% odbijalnosci), i rozproszenie 50%
GynvaelRT.AddLight(Vector3D(2.0, 2.0, -3.0), Vector3D(2.0, 2.0, 2.0));
Gynvaelpotem jest dodane swiatlo, niedaleko kamery ;>
Gynvaelpeirwszy parametr to pozycja
Gynvaeldrugi to kolor swiatla
21:55Gynvael2.0 2.0 2.0 - bialy bardzo intensywny
Gynvaelprosze zauwazyc ze to jednoczenie kolor jak i sila swiatla ;>
GynvaelRT.AddSphere(Vector3D(1.0,0.0,0.5), 0.4, PolishedStone);
GynvaelRT.AddSphere(Vector3D(-1.0,0.0,0.5), 0.4, Paper);
Gynvaelstandardowe AddSphere z dodanym parametrem
21:56Gynvaelczyli materialem
Gynvaelok
Gynvaelmake test
Gynvaeli ogladamy dump.tga
Gynvael
21:57Gynvaeltak to wyglada ;>
Gynvaelpo lewej mamy kulke-papier
Gynvaelpo prawej zielona z refleksyjnoscia
Gynvaeljak zrozumiec Specular i Diffusive w akcji ?
Gynvaelrzucmy okiem na dwie animacje
21:58Gynvaelhttp://wyklady.net/ray1/diffusive.avi
Gynvaelkulka wyrenderowana z diffusive przyjmujacym wartosci od 0 do 1 (patrzcie wskaznik na dole animacji
Gynvael)
Gynvaelhttp://wyklady.net/ray1/specular.avi
21:59Gynvaelto samo, tyle ze ze specular
Gynvael(kody generujace wszystkie pokazane animacje beda dostepne wraz z logami po wykladzie (pewnie dzien po wykladzie ;p))
22:00Gynvaelok
Gynvaela teraz rzucmy okiem na kod
Gynvaelzauwazmy po pierwsze ze doszly nowe pliki
GynvaelMaterial.*
Gynvaelprosta klasa opisujaca material
Gynvaeloraz Light.*
Gynvaeltez prosta klasa opisujaca swiatlo
Gynvaelwewnatrz RTEngine.* doszlo
Gynvaelstd::vector<Light*> LightList;
Gynvaelczyli lista swiatel
22:01Gynvaeloraz funkcja
Gynvaelvoid AddLight(Vector3D Position, Vector3D Color);
Gynvaelktora robi.. wiadomo co
Gynvael;>
Gynvaeljako ze mamy zupelnie nowy shader w Trace
Gynvaelto rzucmy na niego okiem
22:02GynvaelRTEngine.cpp funkcja Vector3D RTEngine::Trace(Ray ray)
Gynvaelpetla znajdujaca obiekt jest bez zmian
Gynvaelshader - distance zostal zakomentowany
22:03Gynvaelpo nim mamy:
GynvaelVector3D pi = ray.Origin + ray.Direction * dist; // point of intersection
Gynvaelpi - punkt przeciecia
Gynvaelza pomoca rownania o ktorym mowilem wczesniej wyliczamy dokladny punkt przeciecia
GynvaelVector3D prim_color = prim->m.Color;
Gynvaelpobieramy kolor obiektu
Gynvaela nastepnie mamy petle
Gynvaelvector<Light*>::iterator lightiter;
Gynvaelfor(lightiter = this->LightList.begin(); lightiter != this->LightList.end(); lightiter++)
Gynvael{
Gynvael[...]
22:04Gynvael}
Gynvaelktora mozna okreslic jako
Gynvael'Dla kazdego swiatla na scenie...'
Gynvael(przypominam ze wytlumaczenie od strony matematycznej wzorow uzywanych w RT bedzie na drugim wykladzie za tydzien)
22:05Gynvaelpo czym mamy dwa kawalki kodu
Gynvaelif(prim->m.Diffusive > 0.0)
Gynvael{
Gynvaeldouble dot = L.Dot(N);
Gynvaelif (dot > 0.0l)
Gynvael{
Gynvaeldouble diff = dot * prim->m.Diffusive;
Gynvaelcolor += ((*lightiter)->Color * prim_color) * diff;
Gynvael}
Gynvael}
Gynvaelten oblicza czesc odpowiedzialna za swiatlo rozproszone
Gynvaelif(prim->m.Specular > 0.0)
Gynvael{
GynvaelVector3D R = L - N * L.Dot(N) * 2.0l;
Gynvaeldouble dot = ray.Direction.Dot(R);
Gynvaelif (dot > 0)
Gynvael{
Gynvaeldot = pow(dot, 20.0); // dot *= dot; dot *= dot; dot *= dot; dot *= dot;
Gynvaeldouble spec = dot * prim->m.Specular;
Gynvaelcolor += (*lightiter)->Color * spec;
Gynvael}
Gynvael}
Gynvaela ten za swiatlo refleksyjne
22:06Gynvaelprzed nimi jest wspolny kawalek kodu
22:10DJ_cool_Gynvael: 22:06 <@Gynvael> przed nimi jest wspolny kawalek kodu
22:11Gynvaelthx ;>
22:12GynvaelVector3D L = (*lightiter)->Position - pi;
GynvaelL.Norm();
GynvaelVector3D N = prim->Normal(pi);
Gynvaeljest tutaj funkcja o ktorej nie wspomnialem
Gynvaelprim->Normal(pi)
Gynvaeljest to funkcja, ktora MUSI posiadac kazdy obiekt (patrz Primitives.h)
Gynvaelfunckja ta przyjmuje punkt przeciecia
Gynvaeli ma zwrocic WEKTOR NORMALNY dla obiektu w tym miejscu
22:13Gynvaelco to jest wektor normalny ? w duzym skrocie jest to wektor pokazujacy 'w ktorym kierunku obiekt jest zwrocony'
Gynvael(tj gdzie jest jego przod)
22:15Gynvaelw przypadku kuli lub kola
Gynvaeljest ten wektor bardzo prostu uzyskac
Gynvaelmianowicie ten wektor jest rowny wektorowi poprowadzonymi od srodka kuli/kola do punktu przeciecia
Gynvaelnp
Gynvael
22:16Gynvaeltam sa pokazane 3 normale (nieznormalizowane ;p) dla 3ch roznych punktow kola
Gynvaelpo co nam normal ?
Gynvaeldzieki iloczynowi skalarnemu normala oraz promienia
Gynvaelmozemy ustalic pod jakim kontem pada swiatlo w dane miejsce
22:17Gynvael(dokladnie o matematyce bedzie na nastepnym wykladzie jak juz mowilem ;>)
Gynvael*katem (rany ;p)
22:18Gynvaelok ;> mamy dwa rodzaje swiatel
Gynvaelrzucmy okiem na animacje 3ch kul ;>
Gynvaelhttp://wyklady.net/ray1/anim1.avi
Gynvael(211kb)
22:19Gynvaeljuz jakos zaczyna to wygladac
Gynvaelmamy juz dwa rodzaje dzialania swiatla
Gynvaelna obiekt
Gynvaeldodajmy jeszcze na koniec tej czesci wykladu odbicia
Gynvaeltj odbicia lustrzane
22:20Gynvaeltak zeby jedna kula mogla 'przejrzec sie w drugiej'
Gynvaelhttp://wyklady.net/ray1/r6.zip
Gynvaelco nowego potrzebujemy ?
Gynvaelpo pierwsze w materiale, informacji na temat jak bardzo obiekt jest lustrzany
Gynvaeldouble Reflective;
22:21Gynvaelstandardowo, od 0.0 do 1.0
Gynvaelskompilujmy sobie i odpalmy
Gynvaelstandardowo juz powstanie pliczek dump.tga ;>
22:22Gynvael
Gynvaeljako ze lewa kulka jest matowa
Gynvaelto nic nie odbija
22:23Gynvaelnatomiast po lewej stronie prawej kulki
Gynvaelwidac odbicie lewej ;>
Gynvaelrzucmy okiem na kolejna animacje ktora prezentuje wplyw wspolczynnika odbicia na wyglad sceny
Gynvaelhttp://wyklady.net/ray1/refl.avi
22:24Gynvaela teraz zastanowmy sie jak uzyskac w raytracingu informacje na temat tego co jest odbite w danym miejscu
Gynvaelsprawa wyglada dosc prosto
22:25Gynvaelmianowicie musimy stworzyc i wystrzelic nowy promien
Gynvaelz miejsca odbicia, w kierunku gdzie odbity promien by polecial (tj odbijamy promien oryginalny od obiektu, tak jak na fizyce nas uczono ;>)
Gynvaeldostajemy dzieki temu informacje zwrotna z kolorem w co ten 'odbity promien' trafil
22:26Gynvaeli ten kolor mozemy pomnozyc przez wspolczynnik odbicia
Gynvaeli dodac do koloru wyjsciowego
Gynvaeldouble refl = prim->m.Reflective;
Gynvaelif(refl > 0.0 && refl_depth < 4)
Gynvael{
GynvaelVector3D N = prim->Normal(pi);
GynvaelVector3D R = ray.Direction - N * (ray.Direction.Dot(N) * 2.0);
GynvaelVector3D rcol( 0, 0, 0 );
Gynvaeldouble dist;
GynvaelRay tempr(pi + R * 0.0001, R);
22:27Gynvaelrcol = Trace(tempr, refl_depth + 1);
Gynvaelcolor += rcol * refl * prim_color;
Gynvael}
Gynvaeljak widac funkcji Trace doszedl dodatkowy parametr, ktory mowi o zaglebieniu rekurencyjnym
Gynvaelw tym wypadku pilnujemy po prostu zeby wiecej niz 4ry zaglebienia odbicia nie byly ;>
Gynvaelw sumie standardowa rekurencja, nic wiecej
22:28Gynvaeldobra ;>
Gynvaelrzucmy okiem na animacje z odbiciami
Gynvaelhttp://wyklady.net/ray1/anim2.avi
22:29Gynvaeli to w sumie tyle jesli chodzi o dzisiejszy wyklad ;>
Gynvaelzapraszam do glosowania i komentowania -> http://forum.wyklady.net/index.php?topic=77.0
Gynvaeljeszcze 3 slowa na temat tego co bedzie na nastepnym wykladzie
22:30Gynvaelprzede wszystkim postaram sie wyjasnic te wzorki matematyczne
Gynvaelintersekcje etc
Gynvaeldlaczego swiatlo obliczamy tak a nie inaczej etc
Gynvaelpo za tym powiem tez o cieniach,
Gynvaelwprowadze do silnika inne obiekty - np trojkaty
22:31Gynvaelpojawi sie tez teksturowanie (z i bez filtrowania)
Gynvaelmaterialy per vertex w trojkatach
Gynvaela na koncu mapy materialow (czyli wlasnie textury, mapy refleksji, bumpmapy, etc etc)
22:32Gynvaelbeda tez 3 slowa o optymalizacji
Gynvaelczyli zamiast listy -> octtree ;>
Gynvaeli w sumie tyle ;>
Gynvaeldziekuje za przybycie ;> i zapraszam na nastepna czesc (termin na dniach pojawi sie w terminarzu)