Lekcija 9: Svijetla i materijali
3D prostor nemože se zamisliti bez svijetla koji realistično osvjetljavaju pojedine objekte u sceni. Iako je u stvarnom svijetu osvjetljavanje objekata jedan vrlo složen fizički proces, on se može u dobroj mjeri aproksimirati i u umjetnom D3D prostoru. Proces osvjetljavanj u 3D grafici naziva se sjenčanje. Sjenčanje se obično obavlja u tri koraka, prvo se računa difuzna komponenta svijetla, zatim spekularna(zrcalna), a na kraju se još dodaje konstantna ambijentna vrijednost. Difuzna komponenta je najbitnija, i ovisi o udaljenosti objekta od svijetla, materijalu od kojeg se objekt sastoji te relativnog položaja plohe objekta prema svijetlu. Spekularna komponenta također ovisi o udaljenosti i polozaju objekta prema svjetlu, no njeno računanje je uvelike zahtjevnije. Spekularno svjetlo očituje se kao sjajni odraz izvora svjetla na materijalu. Ambijentno svijetlo nema smijera, niti položaja, već se dodaje kao konstantna vrijednost boji materijala.
U DirectX-u postoje 3 primarne vrste svijetla, to su direkcijsko(directional light), točkasto(point light) i usmjereno(spot light) svijetlo. Direkciono svijetlo je ono koje je proporcionalno dalekom izvoru svijetla, npr. Suncu, dakle sve zrake svijetla dolaze iz istog smjera. Zadaje se svojim smjerom, te difuzijskom, spekularnom i ambijentnom komponentom. Točkasti izvor svjetla djeluje u svim smjerovima od svoje pozicije, te se također zadaje sa tri komponente, te položajem. Usmjereno svjetlo je isto kao i točkasto osim što mu je kut svjetla ograničen.
DirectX računa osvjetljenje prema položaji objekta koji osvjetljavamo. To se obavlja tako da se intenzitet svjetla u nekoj točki računa kao skalarni produkt zrake prema svjetlu i normale plohe koja se osvjetljava, što govori da je za svaku plohu potrebno zadati normalu. Ovaj način računanja ima svoje nedostatke, npr. Osvjetljenji objekt je osvjetljen i sa jedne i sa druge strane, te sva svjelost prolazi kroz objekte. Ovo stvara dodatne probleme kod realističnih prostora, jer onemogoćuje jednostavno crtanje sjena, koje se moraju crtati i računati naknadno.
Za ralistično sjenčanje nije dovoljno samo zadati parametre svjetla, već je potrebno i zadati parametre materijala koji se osvjetljavaju. Nije svaki objekt osvjetljen bijelim svijetlom bijel. Dakle biti će potrebno definirati i difuznu, spekularnu i ambijentnu komponentu materijela o kojima će ovisiti konačna slika osjenčanog objekta.
DirectX računa intenzitete svjetlosti po pojenim verteksima, ne po cijeloj površini objekta, teje potrebno također potrebno zagladiti granice među pojedinim plohama koje se nalaze pod različitim kutevima. D3D ima dvije osnovne vrste sjenčanja, flat shading i gouraud shading. Način sjenčanja podešava se pomoću SetRenderState metode.
U DirectXu svjetlo se opisuje strukturom D3DLIGHT9 koja sadrži sve potrebno za opisivanje svjetla.
typedef struct _D3DLIGHT9 {
D3DLIGHTTYPE Type;
D3DCOLORVALUE Diffuse;
D3DCOLORVALUE Specular;
D3DCOLORVALUE Ambient;
D3DVECTOR Position;
D3DVECTOR Direction;
float Range;
float Falloff;
float Attenuation0;
float Attenuation1;
float Attenuation2;
float Theta;
float Phi;
} D3DLIGHT9;
Type može biti D3DLIGHT_POINT,D3DLIGHT_SPOT, D3DLIGHT_DIRECTIONAL.
Point light se zadaje položajem, difuzno, i spekularnom komponentom, ali nema smera, te vrijednost kuteva Theta i Phi nisu bitne. Spot light se zadaje sa istim parametrima kao i point light, ali ima smjer, te šitina stožca osvjetljenja ovisi o kutevima Theta i Phi. Directional light nema položaja, već samo smjer.
U primjeru, možete mijenjati vrstu osvjetljenja pritiskom na tipke S, P i D.
Prije svakog osvjetljavanja potrebno je zadati i izračunati normale svakog verteksa na sceni. U tu svrhu FVF format koji koristimo za vertekse plohe su prošireni sa normalom:
|
#define PLOHAFVF (D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_DIFFUSE|D3DFVF_TEX1) |
Struktura sada izgleda ovako:
|
struct CPlohaFVF { float x,y,z;//pozicija, odgovara flag-u D3DFVF_XYZ float nx,ny,nz;//pozicija, odgovara flag-u D3DFVF_XYZ DWORD color;//boja, odgovara flag-u D3DFVF_DIFFUSE float u,v;//koordinate texture, odgovara flag-u D3DFVF_TEX1 }; |
Isto tako moramo zadati normalu po svakom verteksu pri punjenju verteks buffera:
|
pVertices[0].x=0; pVertices[0].y=0; pVertices[0].z=.5; pVertices[0].nx=0; pVertices[0].ny=0; pVertices[0].nz=1; pVertices[0].u=number; pVertices[0].v=number; pVertices[0].color=color; |
Ploha također sada ima i svoj materijal. Diffuse komponenta verteksa određuje istu komponentu materijala, no sada možemo zadati i druge komponente materijala, tj. spekularnu i ambijentnu komponentu, te emisiju samog materijala. Temeljna struktura koja opisuje materijal je D3DMATERIAL9.
typedef struct _D3DMATERIAL9 {
D3DCOLORVALUE Diffuse;
D3DCOLORVALUE Ambient;
D3DCOLORVALUE Specular;
D3DCOLORVALUE Emissive;
float Power;
} D3DMATERIAL9;
U programu materijal se postavlja na defaultnu vrijednost:
|
ZeroMemory( &material, sizeof(D3DMATERIAL9) ); material.Diffuse.r = material.Ambient.r = 1.0f; material.Diffuse.g = material.Ambient.g = 1.0f; material.Diffuse.b = material.Ambient.b = 1.0f; material.Diffuse.a = material.Ambient.a = 1.0f; material.Specular.r = 1.0f; material.Specular.g = 1.0f; material.Specular.b = 1.0f; material.Specular.a = 1.0f; |
Efekt ovoga se vidi kada plohe na sceni osvjetlimo.
Promijenjeno je također dinamičko ponašanje CMesh klase još jednim vektorom unutar kojeg je zadano pomicanje mesha svaki turn.
Svjetla i manipulacija njima izvedena je pomoću CLight klase koja ima svoje Set i Get metode. Neću ih sve opisivat, a možete ih pogleadti u kodu u light.cpp i light.h datotekama.
Pri računanju osvjetljenja intenzitet svjetla se množi sa materijalom koji se osvjetljava, tako da konačno osvjetljenje ovisi o parametrima materijala i svijetla, te njihovom međusobnom položaju.
Da bi omogućili osvjetljavanje u DirectX-u, moramo to napraviti podešavanjem stanja D3D uređaja. To se izvodi u InisijalizirajD3D metodi CScene klase:
|
// Ne koristimo nikakva svjetla na sceni i iskljuciti cemo lighting D3DDevice->SetRenderState( D3DRS_LIGHTING, TRUE ); // Podešavamo ambientnu komponentu svjetla na cijeloj sceni D3DDevice->SetRenderState( D3DRS_AMBIENT, D3DCOLOR_XRGB(20,20,75)); |
Ovdje također podešavamo jačinu ambijentnog svjetla na cijeloj sceni.
Detekcija pritisnutih tipki ispituje se u ProcessKeyboard metodi, i u njoj se podešavaju parametri svijetla nakon pritiska na tipku.
|
if(KEYDOWN(KeyboardState, DIK_P)) { scene->light->SetType(D3DLIGHT_POINT); scene->light->Refresh(); } if(KEYDOWN(KeyboardState, DIK_S)) { scene->light->SetType(D3DLIGHT_SPOT); scene->light->Refresh(); } if(KEYDOWN(KeyboardState, DIK_D)) { scene->light->SetType(D3DLIGHT_DIRECTIONAL); scene->light->Refresh(); } |
Model sjenčanja također se odabire pritiskom na tipku.
|
if(KEYDOWN(KeyboardState, DIK_F)) { scene->D3DDevice->SetRenderState(D3DRS_SHADEMODE,D3DSHADE_FLAT ); } if(KEYDOWN(KeyboardState, DIK_G)) { scene->D3DDevice->SetRenderState(D3DRS_SHADEMODE,D3DSHADE_GOURAUD ); } |
Izgled devete aplikacije

Made by: Mll
Prev Next