DirectX - škola

poruka: 10
|
čitano: 5.202
|
moderatori: Lazarus Long, XXX-Man, vincimus
1
+/- sve poruke
ravni prikaz
starije poruke gore
15 godina
protjeran
offline
DirectX Škola

Davnih Dana, kada se takt procesora još mjerio u megahercima, a assembler vladao svijetom, programiranje aplikacija zahtjevalo je detaljno poznavanje hardvera i to na najnizoj mogucoj razini. Samo kontroliranje unosa na tipkovnici je već bila znanost za sebe, no ujedno i sve druge stvari koje se danas uzimaju zdravo za gotovo. Svaka aplikacija je iznova morala rjesavati jedan te isti problem. Programeri su više vremena provodili pokušavajući natjerati odredeni komad hardvera da proradi na zadovoljavajući način, nego sto su provodili razvijajuci same aplikacije. Porast broja hardverskih komponenti zahtjevalo je dodatno programiranje kako bi se omogucila kompatibilnost sa hardverskim trzistem.

Tek su se pojavom prvih Windowsa počele stvari mjenjati. Od ključne vaznosti za Windowse i samu PC platformu je bilo olaksanje posla developerima, a i samim krajnim korisnicima. Dolazi do kreiranja prvih API-a (Applicattion Programing Interface), ljuski koje bi trebale olaksati komunikaciju s raznolikim hardverom na takav način da API komunicira sa hardverom, a programeri sa API-jom. Iz početka, svaki API je bio vrlo bugovit, slabo dokumentiran, no stvari su se počele polako mjenjati...

Razvijen unutar Microsofta tijekom 1994. I 1995. Godine, svjetlo dana je ugledao sa Windowsima 95 i DirectX API, verzija 2.0. Kako se razvijala tehnologija, razvijao se i DirectX. Postajao je sve kompleksnij, sve veci i fleksibilnij, ali i sve moćnij alat za komunikaciju sa hardverom. Sam DirectX se sastoji od nekoliko djelova, a to su:

DirectDraw – brine se za rasteziranu grafiku.

Direct3D – Zaslužen za 3D grafiku

DirectInput – Brine se za sve ulazne komponente (tipkovnica, joystick, miš, itd...

DirectSound – Zadužen za .waw datoteke

DirectMusic – Prošireni DirectSound koji i dalje koristi isti API za svoj rad.

DirectPlay – Brine se za mrežne protokole i kompletni MP doživljaj u igrama.

Što je to DirectX?

DirectX ( u nastavku DX) je application programing interface, tj. laički rečeno skup naredbi, metoda i funkcija koje kontroliraju hardver na najnižoj razini. Pojasnit cu ovo malo...

I sami znamo da postoji velik broj grafičkih kartica. One, u osnovi rade na približno iste stvari, ali svaka na svoj način. U takvoj situacij postoji nekoliko razina na kojima se upravlja radom tih kartica. Da, programeri mogu napraviti aplikaciju koja šalje instrukcije u točno tom obliku kakav zahtjeva pojedina grafička kartica. Ali, onda ta aplikacija nebi radila na drugoj grafičkoj kartici. Direct3D je jedna od razina kontrole hardvera koja rješava ovaj problem. Proizvođači grafikčkih kartica moraju se pobrinuti da njihov proizvod podržava DirectX. Recimo, korinsik pošalje odredeni zahtjev za iscrtavanje odredene geormetrije. Direct3D pripremi sve stvari potrebne za taj zahtjev i prosljedi ih najnizoj razini, samim driverima grafičke kartice. Direct3D ( u daljnem teksu D3D) je napravio sve to, eliminirajuci potrebu da to programer radi.

Napraviti aplikaciju koja će moći rasditi na tim svim karticama bilo bi nemoguće bez DirectX-a. Nemorate voditi čak ni brigu o kakvom se hardveru radi; Da li ce taj hardver biti u buducnosti ili je on sada na trzistu. Vi radte softver koji je DirectX kompatibilan, a DX ce se pobrinuti da on radi na različitom hardveru. U tu svrhu uvedena su dva sloja rada: HAL i HEL

Hardware Abstraction Layer (HAL) – koristi hardverske resurse za svoj rad, ukoliko ti isti resursi nisu dostupni (nema hardvera), koristi se Hardware Emulation Layer (HEL) koji emuliraja odredeni komad hardvera koji nedostaje.

Još jedna bitna stvar u DX. DX se razvijao i rastao, no njegova bitna osobina je backward compability; svaka nova verzija je unatrag kompatibilna sa starijom verzijom (iznimka DX10). Tako da aplikacije pisane recimo za, DX8.1 bez problema rade sa svim novijim revizijama i na proizvedenom hardveru.

Još jedna velika prekretnica u svjetu DX je dosla s verzijom DX8.1, koji je uveo shadere. Shaderi su u biti mali komadici koji kontroliraju na odredeni način da se obraduju pojedini vertexi/pixeli. Svaka verzija shadera donosi nesto novo, veci broj naredbi, prosirene registre...

Isprva su shaderi bili pisani u običnom, tekstualnom obliku, koje je kasnije DX prevodila u jezik poznat grafičkom hardveru. Jezik je bio sličan assembleru, sa nekim modifikacijama. Tada je na scenu stupa HLSL – odnosno High Level Shadnig Language, jezik koji je sličan C-u, ali samim time preglednij i jednostavnij. Princip, je opet doduše ostao isti. Napišete shader u HLSL-u, compiler pretovori kod u kod prepoznatljiv grafičkom hardveru i stvar je rješena. No, ono što je ogromna prednost HLSL-a je ta što možete birati za koju verziju shadera želite kompajlirati shader. Recimo, ako grafička podržava shadere 3.0, možete ga kompajlirati za tu verziju, no ako podržava samo 2.0 shader, možete isti taj shader kompajlirati u istoj toj verzij bez ikakvih modifikacija. Ponekad to nije moguće zbog ograničenja samog shadera, no ako se pripazi pri programiranju, moguće je ostvariti maksimalnu fleksibilnost shadera.

Kao što je rečeno, DX je započeo svoj život kao alat koji olaksava stvar programerima. Prednost DX nad ostalim API-ima je ta što on obuhvaća sve komponente koje ce ijednom prosječnom programeru zatrebati. No, nije ni DX bez grijeha. Glavni problem je što je to Microsoftov prizovod, što znači da ide samo na Windows i Xbox platformu. Tako da, ukoliko poželite izdati i svoju aplikaciju za Mac OS reciimo, morate posegnuti za OpenGL.

DirectX je s druge strane besplatan. Moguće ga je s neta skinuti, no isto tako je moguće i skinuti DX SDK (Software Development Kit) koji će vam učiniti programiranje s DX-om puno jednostavnije.

Kada je riječ o razvoju DX-a, Microsoft i proizvođači usko surađuju. Oni slušaju developere, slušaju sve prijedloge sto bi zeljeli u iducim verzijama. Recimo, shaderi su uvedeni zbog potrebe da dodatno kontroliraju procesiranje geometrije piskela, kao i zbog potrebe za većom fleksiblnošću hardvera. DX je u biti custom made.

Direct3D

Najzanimljivija komponenta DX-a je Direct3D, iz par razloga. Prvi je naravno, brutalno brz razvoj grafičkih karticai njihovih mogućnosti, koje naravno kontrolira Direct3D. Drugi razlof je najatraktivnij dojam koji ta komponenta zadužena za 3D grafiku ostavlja.

DirectX je implementiran preko COM (Component Object Model) objekata, i programeri koji rade u C++ koriste D3D direktno. Nije potrebno poznavanje COM-a da bi se radilo u D3D-u. Osnovni pojam
kod D3D-a je device. Preko D3D-a Create funkcije dobijemo pokazivač na D3D sučelje. Nakon što dobijemo sučelje, izabrat ćeno prozor koji želimo kontrolirati, te kreirati sam Device preko kojeg ćemo pristupati funkcijama koje želimo. Prvi i najbolnij korak je preden.

Prije nego što navalimo na D3D, potrebno je malo objasniti sam koncept 3D svjeta.

Zaslon Monitora, kao primarna izlazna jedinica, je naravno dvodimenzionalan. Emuliranje 3D prostora predsatvlja kompliciranu zadaću i potrebno mu je posvetiti dosta pažnje, a u cjelu priču je i upleteno dosta matematike. Uzmimo običnu točku koju smo postavili u naš neki imagirani 3D kordninatni sustav. Nazovimo tu točku Vertexom. Vertex čini osnovnu komponentu svakog 3D modela, to je obična točka koja je posavljena u neki 3D prostor. Njeno osnovno svojstvno je da ima poziciju koja se prikazuje 3D vektorom. Redovno, vertexi imaju još svojstava, no za sada ćemo se samo zadovoljiti sa svojstvom točne pozicije u prostoru.

Najosnovnij geometrijski model je trokut. On se sastoji od tri vertexa i služi kao osnovni gradevni element za sve naše modele. Znači, imamo neku imagiranu točku u nekom imagiranom 3D svjetu. U igru sada dolazi novi pojam; vertex buffer. Samo ime govori; Riječ je o memorij u koju se spremaju vertexi.

Direct3D je u jednu priču uveo još jedan zanimljiv koncept – kameru, odnosno oko onoga koji gleda tu točku. Podstavimo tu točku u ishodiste kordinatnog sustava i odmaknimo se malo od nje. Recimo da pozicija predstavlja poziciju našega oka, i početnu točku odakle se promatra. Bitne su 3 stvari: odakle gledamo, gdje gledamo, i u kojem smjeru gledamo. To su takozvani position, lookat, i up vektori i oni medusobno kombinirani čine svojevrsnu matricu. To je takozvana view matrica, prva od tri matrice koje su nam bitne u D3D. Ukoliko znamo ta 3 vektora, možemo postaviti kameru u bilo kojoj pozicij u nešem 3d svjetu, i promatrati ga. No, kada bismo promatrali samo preko view matrice, slika bi nam se deformirala ovisno o pozicij kamere i kutu pod kojim bisno gledali neko objekt.

Iz tih razloga je uvedena projection martica, koja popravlja persektivu i stavlja sliku ovisno o danim parametrima. Da bi kreirali jednostavnu projection matricu, potrebno je znati koja nam je najbliža točka koju vidimo, kao i udaljena. Još je samo potreban omjer našeg ekrana i to je to.

Nakon što smo uveli te dvije matrice, možemo bez problema postaviti u 3D prostor. Rezultirajuća slika na našem monitoru će biti zadovoljavajuća. Nakon što smo postavili matrice i napunili naš vertex buffer koordinatnim točkama, moramo još postaviti sve te parametre i spremni smo za crtanje naše prve točke!

 

Z-buffer

Z-buffer se naziva još i depth bufferom,   i on sadrži podatke o dubini odnosno udaljenosti pojedninih elemenata ovisno od položaja našeg oka. Super, ali čemu on služi? Stara poslovica kaže: "najbrže se rendeira ono što se ne rendeira". Ukoliko se jedan objekt nalazi ispred drugogm, ovaj potonji se nevidi, nije li tako? Upravo ovdje leži razlog jedne od optimizacija igrara. Z-buffer je upravo stvoren u tu svrhu. Vi prosljedite geometriju na iscrtavanje, a nakon rasterizacije odreduje se jeli dubina koja se nalazi u Z-bufferu. Ukoliko je vidljiva, D3D je iscrtava na ekranu. Ukoliko nije vidljiva - grafička kartica ju jednstavno preskoči.

No, Z-Buffer ima još jednu zanimljivu osobinu. Naime, raspodjela gustoće dubine nije linearna. "Near plane" i "far plane" definirane su u projection matrici. Recimo, da smo za najbližu odabrali jedan metar, dok smo za najdulju odabrali 100 metara. Z-Buffer ima na raspolaganju 24bita. Tih 24 bita u našem slučaju nije linearno rasporedeno. Moderne igre pridaju posebnu pozornost   detaljima koje su bliže oku, dok objekti u daljini jednostavno se gube na detaljima. Z-buffer je koncipiran na taj način da se u pravilu 90% njegovih mogućnosti 10% troši na dubine najbliže vama, kako bi se osigurala najbolja moguća kvaliteta.

Nemali broj grafičkih kartica   kompresira z-buffer kako bi smanjile memorijsko zauzeće i prije svega ubrzale cjelu stvar. Ukoliko je z-buffer previše rastrgan, dolazi do suprotnog efekta: kompresija z-buffera uzrokuje usporenje. Doduše, na modernom hardveru to nije ništa strašno, no pametan programer broji svaku sitnicu.

Stigli smo do prvog djela.

Očekujte sutra nastavak - Sutra ćemo se pozabaviti shaderima!

Z-Buffer Z-Buffer
Evo ide nevjesta preljepa je zaista
Poruka je uređivana zadnji put sri 2.9.2009 16:03 (fabijan654321).
 
13 0 hvala 15
15 godina
protjeran
offline
DirectX Škola

Da ne ulazi u prvu poruku ovdje ću prikazati primjer shadera:

PRIMJER PISAN U HLSL-u:

float4x4view_proj_matrix: register (c0);

float4 lightPos: register (c4);

struct VS_OUTPUT (

float4 Pos: POSITION

float3 normal: TEXCOORD0;

float3 lightVec: TEXCOORD1;

);

VS_OUTPUT main(float4 Pos: POSITION, float3

normal: NORMAL)(

VS_OUTPUT Out;

Out.Pos = mul (view_proj_matrix, Pos);

Out.normal = normal;

Out:lightVec = lightPos - Pos.xyz;

return Out ; ) ;

 

Identičan shader ćemo isprogramirati i u assemblerskoj verzij:

vs_1_1

dcl_position v0

dcl_normal v1

mul r0,   v0.y,   cl

mad r0,   c0,   v0.x,   r0

mad r0,   c2,   c0.z,   r0

mad oPos,   c3,   V0.w,   r0

ADD oT1-xyz,   -v0,   c4

mov   oT0.xyz,   v1

 

Evo ide nevjesta preljepa je zaista
Poruka je uređivana zadnji put sri 2.9.2009 16:09 (fabijan654321).
 
8 0 hvala 10
16 godina
neaktivan
offline
DirectX Škola

Samo par ispravaka:

- kod kamere su bitni Up, Left i Direction vektori. Look at je funkcija koja kalkulira to troje od trenutne pozicije. Drugi vrlo bitan parametar je frustum. Kameru takodjer nije uveo DirectX jer viewport postoji u 3D matematici odavno :-)

- projekcijska matrica ne mora biti perspektivna, moze biti i ortogonalna - u tom slucaju su frustum parametri nepotrebni

- tocka se ne moze iscrtati :-) neophodno je imati minimalno 3 tocke za minimalni primitiv: triangle. A za triangle je neophodno imati jos minimalno vezni buffer (indices) i normale ili boju, ovisno da li koristimo osvijetljenje ili ne.

- funkcija za depth buffer se izvrsava prilikom pisanja, fragment koji nije zadovoljio funkciju je discardan; 'pokriveni' fragmenti su nedostupni u depth bufferu

- nelinearnost depth buffera nije nesto sto danasnje igre iskoristavaju, dapace nasuprot: vecina modernih deferred renderera renderira svoj linearni depth buffer. Po meni nepotrebna praksa, jer depth buffer je nelinearan s razlogom: detalji trebaju blizu kamere (odnosno blizu near planea) a sto dalje ides, ionako se texeli filtriraju.

 

Pored toga,

svaka cast na trudu i znanju!

"Fans are clinging complaining dipshits who will never ever be happy for any concession you make. The sooner you shut up their shrilled tremolous voices, the happier are you going to be for it.&q
 
6 0 hvala 8
15 godina
protjeran
offline
RE: DirectX Škola

To sada nek stoji, neda mi se sada editirat, pogotovo jer bug forum ima očito jako velikih problema s novom verzijom opere, pa nemogu čak ni ovo kako bog zapovjeda napisat.

Evo ide nevjesta preljepa je zaista
15 godina
protjeran
offline
DirectX Škola

Dobrodošli u drugu lekciju DirectX-a! U ovom članku ćemo se pozabaviti shaderima u DX-u.

Prvo da kažemo par riječi općenito o shaderima.

Svaki programer teži za boljim. U početcima ako ste htjeli dobiti ikakav ispis na ekranu morali ste se primiti assemblera i fino upgrenuti procesor da obavlja posao. 3D? Zbog hardverskih ograničenja 3D je bio čista fikcija. Naravno da to nije bilo zadovoljavajuće za programere; Došao je jači hardver pa su programeri mogli uz par optimizacija i fakeova stvari ubaciti u 3D prostor. Naravno, s programerske strane išlo se na nižu razinu, kako bi se optimiziralo do krajnih granica. S pojavom prvog specijaliziranog hardvera stigli su i prvi API-i koji su uvelike olakšali život programerima. No, pojavio se opet problem. Scena u 3D prostoru sastoji se od nekoliko osnovnih elemenata, prvenstveno vertexa kao osnovne građevne jedinice i pixela kao kvanta vizualnog prikaza. Budući da je u ovoj točki rukovanje 3D-om jedonstavno, zahtjevi programera su se povećali. S obzirom na arhitetkturu grafičkih kartica, pronađen je kompromis. Svjetlo dana sa DX8.1 ugledali su Shaderi.

Da pojasnimo malo pojam shader.

Dakle, kroz internu arhitekturu modernih grafičkih kartica rukuje se sa svega od par elemenata. Najčešće su vertexi koji čine objekte i teksture, što im daje detaljnost. Svemu što se dešava u memorij grafičke kartice pristupate indirektno, funkcijama koje su dostupne kroz DX. Isto vrjedi za postavljenje odredenih stanja, odnosno za definiranje odredenih pravila koje će se odnositi na objekte koji se trenutno obraduju od strane grafičke kartice. Ono što je ovdje problem je brzina komunikacije. Recimo ako želite "probrćkati" po odredenom vertex bufferu koji drži odredenu geometriju, imat ćete jako dugo čekanja. I, naravno postavlja se pitanje kako promjeniti neko odredeno pravilo na odredenu grupu objekata, a da to nebude sporo. Odredenu razinu  slobodu   uvjek ste i imali;   doduše kroz nekoliko predefiniranih postavki unutar Fixed Function Pipieline-a, ali za neke kvalitetnije postavke to jednosavno nije bilo dovoljno. I nakon toga su stigli shaderi. Shaderi su definirali pravila koja se odnose na objekte s kojima trenutačno radimo. Postoje dvije vrste shadera: Vertex Shader i Pixel Shader. Vertex shaderi definiraju pravila koja se odnose na svaki vertex koji se iscrtava, dakle transformacije i osvjetljenje i sve vezano uz to. Imate nekoliko ulaznih i izlaznih registara; što ćete raditi s njima ovisi o vašoj mašti. Bitno je da samo izbacite poziciju vertexa koji ste obradili. Pixel shaderi su ista stvar, no za pixele te definiraju svaku stvar s kojom će pixel biti podložan.Ugrubo rečeno, postavite da vam svvi modeli imaju plavu boju, te ukoliko sada želite nešto promjeniti, nemorate petljati po vertex bufferu i mjenjati postavke samog vertexa već je dovoljno promjeniti shader. Ista stvar vrijedi i za Pixel shadere.

Pojavom DX8-a pojavili su se i dotični shaderi. Programiranje shadera ispočetka se radilo u assembleru, dakle skidala se prašina sa starih knjiga te se prisjećalo prošlosti. Iako nije riječ o klasičnom assembleru, već o njegovoj novijoj inačici, princip je ostao isti. Početci su bili poprilično bolni. S obzirom da je bilo riječ o novoj tehnologij, nije bilo dovoljno literature, niti alata. Jednako tako, nije ni postajao velik broj grafičkih kartica koje bi to podržale, pa je se to ispočetka smatralo nepotrebnim. Nadalje, trebalo je dosta muke da bi isti rezultat koji bi dobili kroz razne kombinacije unutar Fixed Function Pipeline-a. A i nije bila rijetkost da rezultat koji izgleda da je isto nesto kao iz Fixed Function Pipelinea radi bitno sporije od navedene inačice... Onda čemu vse to pitate se? Ipak shaderi su jedna od najboljih stvari koja se dogodila računalnoh grafici.

Kada želite iscrtati odredenu geometriju, morate postaviti i odgovarajuće vertex buffere. Svaki vertex se sastoji od osnovnih dijelova: Prvenstevno pozicija, normala, i teksturne koordinate. Kako bi nas shader ispravno prepoznao elemente koji mu dolaze brine se ova deklaracija:

 

D3DVERTEXELEMENT9_Decl[] =

[

          [   0,     0,   D3DDECLTYPE_FLOAT3,

D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0],

                                                                                  [       0,     12     D3DDECLTYPE_FLOAT3,

D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL,   0],

                                                                                [     0,       24,     D3DDECLTYPE_FLOAT2,

D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0],

D3DECL_END()

];

Pomoću gore navedenog formata definirat ćemo poziciju, veličinu i svrju svake pojedine komponente vertexa. U našem primjeru možemo zaključiti da će nam prvi element biti veličine 3x Float (3x4=12) te da će biti na početku samog vertexa. Zauzimat će 12 byteova i ova komponenta će sadržavati informaciju o položaju vertexa. Sljedeći element iste veličine, fizički počinje ondje gdje prestaje pozicija, dakle od 12 pa do 24 bytea... Ovo ćemo pretvoriti u deklaraciju vertexa (LPDIRECT3DVERTEXDECLARATION9) te ćemo omogućiti našem malom shaderu da se snade medu tim podacima koje smo utrpali. Dakle, svaki shader počinje oznakom u kojoj je verzij pisan.

Nakon ovoga, sljedi shaderova interpretacija podataka u koju će ulaziti:

dcl_position v0

dcl_normal0   v1

dcl_texcoord0   v2

Ustvari smo samo povezali prvi element s ulaznim registrom v0, drugim registrom v1, itd...Jeli u pitanju pozicija, normala ili nesto sedmo nije nam sada bitno. To su samo nakupine byteova koje tek kasnije postaju ono što želimo da postanu. Nakon što smo ovo napravili spremni smo za "šamaranje" vertex elemenata. Recimo da zelimo transformirati poziciju s world, view i projection matricom.

m4x4, r0, v0, c0, nam predstavlja privremeni registar koji nam služi za privremene rezultate i kalkulacije. v0 je prvi element svakog vertexa, dok nam c0 predsavlja konstantu koju smo napunili unutar svoje aplikacije.

d3d- >SetVeretxShaderConstantF(0,     (float*)   &   neka_matrica,   4);

SetVertexShaderConstantF puni registar s odredenom vrijednoscu. Prvi parametar je broj registara, drugi parametar je sama vrijednost koju punimo, a treci veličina vrijednosti.   Veličina se mjeri u četverokomponentnim vektorima. Ovdje je riječ o matrica koja je veličuine 4x4. Dakle, nakon što smo transformirali poziciju sa svojom matricom, moramo taj rezultat pospremiti na svoje mjesto, odnosno poslati stvari dalje na obradu.

mov oPos,   r0

oPos je izlazni registar koji stavljamo u transormirane vertexe. Uz tu poziciju, na raspolaganju imamo još:

oFog - registar u koji postavljamo podatke o magli koju želimo primjeniti.

oPts - registar u koju spremamo podatke o pojedinim točaka  koje želimo   definirati (prvenstveo point spriteovi).

oD0, oD1 - registri u koje posatvljamo podatke o boji koje želimo kasnioje koristiti u pixel shaderima te oT0-oT7 osam registara koje sadrže informacije o UV vrijednostima.

Naon što smo transofrmirali poziciju vertexa i poslali je dalje u bijeli svijet možemo obraditi iduce komponente vertexa koje nam trebaju.

I dobili smo osnovni shader!

Konačan proizvod bi izgledao ovako:

vs.1.1

dcl_position v0

dcl_normal0   v1

dcl_texcoord0   v2

m4x4   r0, v0,   c0

mov oPos,   r0

mov oT0,   v2

Možete a napraviti u bilo kojem uredivaču tekstualnih datoteka. Dotični shader se moze kompajliati ovako:

ID3DXBuffer*Source=NULL

LPDIRECT3DVERTEXSHADER9   vsh;   D3DXAssembleShaderFromFile("ime_novog_shadera",   NULL,   NULL,   NULL,   &SourceNULL);

D3D - >CreateVertexShader((DWORD*)Source>GetBufferPointer(),&vsh);

I postaviti:

D3D->SetVertexShader(vsh);

Eto, nas shader je spreman za upotrebu. Rezultat nisu spektakularni, no ovo je samo početak...

Dakako, pričati o shaderima nema puno smisla. Shadere jedino možemo vrednovati po onome što čine s jedne strane i što nam novoga omogućuju s nove strane. Mnogi efekti nisu bili mogući prije pojave shadera. Pojavom shadera počela je novo poglavlje računalne grafike, kao što se vidi u novim igrama.   Više ništa nije nemoguće i nema pravih izgovora da rezultat bude manje nego savršen.

 

 

Evo ide nevjesta preljepa je zaista
Poruka je uređivana zadnji put sri 2.9.2009 8:45 (fabijan654321).
 
7 0 hvala 8
15 godina
protjeran
offline
DirectX Škola

Dobrodošli u treću lekciju DirectX-a - Elementi Igara

Dakle shadere smo prošli, sada idemo na elemente igara.

Pogledajmo prosječnu igru. Ona se sastoji od osnovnih elemenata, a to su: Teren, i nebo. Nadalje svijet popunjava razno drveće, raslinje, voda, rijeke te slično. Zatim se dodaju razni statični objekti, kao kuće, zidovi i ostala mrtva priroda. Nakon što smo napravili takav teren, potrebni su nam interaktivni elementi. Oni mogu biti animinirani i neaniminirani. To bi bio osnovni set elemenata za neku igru. Nakon ovoga tu dolaze svjetlosni efekti i prirodne pojave koje se danas isključivo rade kroz shadere (kao što su refleksija, subsurface scatering..), i na kraju dolaze partikli. Za danasnje igre je potrebno brdo partike efekata, pogotovo vatra i dim.

Ono što je specifično za moderan razvoj igara jest činjenica da svaka nova igra podlježe novim standardima u izradi igre. Usljed ovakvog rapidnog razvoja tesko je drzati korak sa najvećim. Svaka komponenta izgleda savrseno i svakim danom bolje. Uzmimo za početak Teren.

Teren je osnovni element većine igara. Ujedno u igrama zauzima velik dio vidljivog područja ekrana, zato je bitno da izgleda savrseno. Kod svakog terena postoje dvije osnovne grupe problema; problemi vezai za vertexe te problemi vezani za tekstuiranje. Idemo polako; Ono sto svima pada na pamet je kada je u pitanju teren jest jedan veeeliki poligon pod nogama koji ima teksturu na sebi i to je OK. OK, to negjde i drzi vodu, al u ovom slučaju ste ograničeni na ravan teren s nemastovitom teksturom. Ukoliko se radi o velikom terenu, i tekstura mora biti velika što je veliki problem. Isto tako, moramo iscrtavati cijeli teren bez obzira koliko je uopće vidljiv u danom trenutku. Dakle, prilično neprihvatljivo.

Heigh Mapa

Hrabri programeri su se odlučili taj veliki poligon razbiti na mrežu manjih; slično kao šahovska ploča. Takav teren se naziva heigh mapa. Dakle, imate linearno raspodjeljene poligone u obliku šahovske ploče, veličine koju god želite. Svaki element ima svoju veličinu i mozete zaista dobiti impresivne veličine uz jednu prednost koju daje linearnost, a to je da mozete uvesti masu optimizacija i krenuti s dosta pretpostavki kod razvijanja algoritma.   Isto samo tako zbog samo lineane strukture programeri nerijetko koriste teksturu za spremanje informacij o visini samog vertexa. Dakle, ako imate teren veličine 256x256 vertexa, uzmete teksturu iste veličine i obojite recimo sivom bojom iscrtate planine i uvale. Recimo da uzmete neutralnu sivu boju kao razinu vode, dok su ovi ispod. I prilikom učitavanja terena, učitate vrijednosti boje i postavite vertex koji odgovara položaju na teksturi na visinu kojoj je odredena vrijednošću boje. Omanje problem bi mogao biti granulacija, odnosno činjenica da se raspon krece od 0 do 255, što daje 256 različitih položaja, no nemojte zaboraviti da imate tri ili četiri komponente koje mozete po vlastitom nahodenju kombinirati :)

Prednost ovog pristupa je što nemorate izmišljati nove standarde za pohranu podataka, i što mozete kreirati teren koristeći alat za obradu slika koji dolaze u paketu sa filterima i sl. uz pomoć kojih se generira teren u roku od par minuta. Isto tako, ljudima je lako predočiti vizualno visinske razlike koje su obilježene sivom bojoj na ovakvoj vrsti topografske karte, rezultat vide trenutno bez potrebe za dodatnim kompliciranjem.

Takav oblik terena koristi dobar dio danasnjih igara. No, ovdje se pojavljuju dva osnovna problema. Prvi je sto je takav linearan oblik ima svojih ograničenja. Recimo kada su u pitanju jako dinamične površine, ovakav oblik terena ne nudi mnogo; sve je predočeno linearnom mrežom, nema izbočina niti oštrih bridova. Isto tako, nema ni kosih elemenata, sve je jednostavno ravno. Ovdje tako postoji drevna opasnost. Da li posaviti veći borj poligona i dobiti veću detaljnost, ili manji pa dobiti nešto veću oštrinu terena, te istovremeno dobiti na perfomansama. Ipak, najveći ovdje problem je tekstuiranje. Osnovni početak bi bio da se naljepi jedna velika tekstura i time se rješi stvar. Ovo čak nije toliko loša ideja ukoliko se radi o manjem terenu čija je veličia fiksna, te da teksture prosječne veličine mogu sve potrebo prikazati. Ovjde je pak mana što vam treba jedna velika tekstura kako bi zadovoljila sve potrebe, te se bas za svaki novi teren mora raditi nova tekstura.

Nadalje, možete se poslužuiti trikom iz 2D igara. Svaka površina naše šahovnice ima svoju sličicu, i konačan teren se dobije popunjavanjem svakog pojedinog polja. No, ovdje je problem što ćete imati masu malih sličica. Isto tako teško ćete se rješiti pravokutnog izgleda komponentnog terena. Puno glavobolje će vam zadati i preklapanje jedne vrste terena sa drugom. Općenito gledajući, ovo pretapanje medusobno različitih vrsti terena čini većinu problema. Zamislite si testni komad terena na kojem imate s jedne strane planinski okoliš koji prelazi u plodne pašnjake na kojima svizac mota čokoladu, a kroz sve to jasno prolazi planinski puteljak. Prisječan prikaz terena bilo koje igre. Problem se postavlja: Kako postaviti različite tipove terena na jedan model, a kako napraviti blage prijelaze i kako napraviti oštre prijelaze medu terenima. Uz to, kako osigurati dovoljno različitih tipova terena, a istovremeno ne pojesti sve dostupne resurse? Jedan od osnovnih načina jest da se sve teksture postave u volumnu teksturu, i to nekim logičnim redosljedom; recimo šljunak u prvi sloj, pa neke prasnjake, pa zatim prijelaz na planinski okoliš, te na kraju tekstura same planine. Prilikom mapiranja na svaki vertex samo dodamo jednu komponentu koja nam govori dubinu volumne teksture koja će se koristiti i to je to. Dakle, ovom metodom mozemo dobiti sve prijelaze, oni će se sami pretapati u jedan drugi zbog karakteristika volumnih tekstura. Odlična stvar, ali problem je taj da bi smo došli do željene teksture moramo neminovno proći svaki put kroz sve teksture koje stoje izmedu trenutne i željene.

Isto tako s obzirom da se radi o mapiranju po svakom vertexu, nemozemo postići detaljne efekte koji su nužni. Ali, pozitivna star je što nam za cijeli teren treba samo jedna tekstura što uvelike ubrzava proces rendeiranja terena i smanjuje eventualne komplikacije. Dakle, i ova metoda ipak ima svoju primjenu, no idemo korak dalje.

Kako bi u potpunosti eliminirali cjeloukupni ovalni i neprofesionalni izgled tekstuiranog terena, možemo se poslužiti lookup teksturom. Odnosno, teksturom koja se ljepi preko terena, a u sebi sadrzi zeljeno visine.   Dakle, sada one dubinske vrijednosti piksela volumne teksture selima sa vertexa na pixel, što nam daje daleko veću preciznost i dinamičniju mogućnost mjenjanja terena na materijalu. Ovdje pak imamo jedan očiti problem, a to je da ce nam trebati jedna jako velika tekstura sa tim vrijednostima, ili više malenih. Dakle, opet se mora napraviti odredeni kompromis. Ukoliko imate uključeno filtriranje za ovu novu lookup teksturu, teren će vam i dalje izgledati ovalno. Ukoliko pak želite isključiti filtriranje, problem nestaje, ali i dalje ostaje kockast izgled, osim ako ne koristite dovolno veliku lookup teksturu, čiji će se pixeli poklapati s pixelima na terenu, no opet dolazimo do problema sa velikim teksturama i njihovim potrosnjama resursa.

Dakle, idealnog rješenja nema, za svaku solucija postoji odredeni niz prednosti, te mana. Potrebno je dobro procjeniti kakav vam oblik terena treba. 

 

Evo ide nevjesta preljepa je zaista
Poruka je uređivana zadnji put sri 2.9.2009 15:48 (fabijan654321).
 
8 0 hvala 7
16 godina
offline
DirectX Škola

Super Tutorial.

Modovi šta čekate dajte sticky.

Da se Facebook server sruši 90% mladih palo bi u tesku depresiju. Ako si u onih 10% koji bi im se smijali stavi ovo u potpis
Moj PC  
2 0 hvala 1
15 godina
protjeran
offline
RE: DirectX Škola
xxxxx kaže...

Super Tutorial.

Modovi šta čekate dajte sticky.

Sada pišem Fixed Function Pipeline, teksture, materijale, bit ce jos puuuno toga obradeno.

Evo ide nevjesta preljepa je zaista
15 godina
protjeran
offline
DirectX Škola

Dobrodosli u četvrtu lekciju DirectX - Teksture i Materijali

Zbog svoje zastarjelosti, FF Pipeline ću samo površno objasniti, to je tu samo radi reda da ne preskočimo legendu :-)

Fixed Function Pipeline je ostavština starih verzija DX-a. Odlika mu je sposobnost i brzina izvrsavanja sa starim i sporijim računalima koje nemaju podrsku za shadere. No, ipak ima i svojih mana. Kod ovakvog načina procesiranja imate puno manje slobode nego sa shaderima. Cijela priča se svodi na postavljanje raznih DX-ovih naredbi (tj. stateova). Konačno, sa DX10 Microsoft je rekao zbogom zauvjek Fixed Function Pipelinu.

Materijal je interna DX-ova struktura koja opisuje svojstva nekog objekta, prvenstveno ovisno o svjetlu. Svjetlo u DX nam dolazi u par oblika:

-Ambient Light

-Diffuse Light

-Specular Light

-Emmisive Light

Konačno osvjetljenje modela dobije se zbrajanjem ovih komponenti.

Ambient Light je osnovna komponenta koja odreduje količinu svjetla koja je vidljiva.

Difuzno svjetlo ovisi prvenstveno o izvoru svjetla, snazi itd.. Sam izvor svjetla može biti Directional (na sve poligone, modele djeluje pod istim kutom), Point (izvor svjetla u obliku točke) i Spot (ima oblik stošca, kao npr. svjetlo ručne svjetljike).

Specular Lighting je jedna zanimljia komponenta. Ona predstavlja komponentu koja je dobivena odbijanjem svjetla.

Emmisive Light je komponenta koja se dobije ukoliko naš model emitira svjetlo. Isto tako rijetko je koristena komponenta (barem u Fixed Function Pipelinu).

Teksture

Pojam tekstuiranja ima dugačku tradiciju. Sve je počelo kada je jedan programer drugom rekao nakon pete, šeste pive "ovaj zid je dosadan, ajmo nesto stavit na njega". Rezultat je bio više nego odličan.  On se sastoji od četiri ugla, četiri vertexa i 4 točke. Ta tapeta nam je tekstura, a model zid. Tekstura je kratko rečeno dvodimenzionalna slika u kojoj se nalaze informacije o vrijednošću boja. Svaka od tih vrijednosti ima svoj položaj koji je u ovom slučaju fiksni. Kako bi maknuli probleme oko fiksnih vrijednosti koje bi mogle raditi probleme ukoliko imamo dugačke veličine tekstura, vrijednost po kojima se krecemo prebačene su sa fiksnih na relativne. Dakle, položaj svakog piksela više nije prikazan pomoću dva indeksa koji imaju raspon od 0 i veličine teksture u tekselima, odnosno 0 i visine teksture u tekselima, već pomoću dvije vrijednosti koje se krecu izmedu 0 i 1. Položaj gornjeg lijevog ugla nam kazuje koordinate 0,0 dok nam je polozaj donjeg desnog uga 1,1. Sada nam veličine tekstura ne predsavljaju problem jer se radi o relativnim vrijednostima.  Kako bismo mogli teksturu naljepiti na naš poligon, svakom smo vertexu dodali jos dvije komponente: U i V. Te se vrijednosti u pravilu krecu izmedu 0 i 1, iako mogu biti vece od 1 kod ponavljanja teksture. Jedan dio nam govori koji dio teksture treba biti u horizontalnom smjeru, a koji u vertikalnom.

Izmedu tih krajnih točaka, vrijednost teksela koji nam treba za odredeni pixel dobije se interpolacijom. To je osnovni princip. Kako nebi bilo sve savrseno, pobrinuo se nas dobri 3D prostor. Prilikom gledanja poligona pod nekim kutom koji nije okomit na njegovu povrsinu, dolazi do deformacija koje su rezultat aproksimiranja prilikom interpolacije. Tako da prilikom rotiranja tekstuiranog modela dolazi do gubljenja piksela, te prevelikih deformacija koje upropastavaju solidan model.Idući problem je vezan uz samu teksturu. Naime, ukoliko naljepite malenu teksturu na odredeni model, te vam model dode u blizinu da vam zauzima većinu ekrana dobijete dobre stare kocke koje su nastale zbog činjenice da nemate dovoljno teksela na teksturi koji bi mogli popuniti sve vrijednosti, tako da jedan teksel zauzima nekoliko piksela na ekranu. Srećom oba problema su rješiva jednom tehnikom - a to je filtriranje.

Filtriranje

Filtriranje radi na jednostavnom principu, uzme se nekoliko okolnih teksela, te se izracuna vrijednost koja nam je potrebna za trenutni pixel. Filtri su se pojavili nedugo nakon tekstuiranja, kompenizirajuci artefakte koji su se pojavljuju. DX prepoznaje tri različite kategorije filtriranja:

-D3DSAMP_MAGFILTER

-D3DSAMP_MINIFILER

-D3DSAMP_MIPFILER

D3DSAMP_MAGFILTER označava pojavu kada se nekoliko piksela na ekranu biva pogodenim jednim te istim tekselom sa teksture. Ovo se desava kada imamo teksturu koja nije dovoljno velika kako bi prikrila svaki teksel sa pikselom, najčešće prilikom zooma, tj. kada nam je model blizu. Ovo bi se dalo riješiti koristenjem velikih tekstura, ali to bi onda jako smanjilo perfomanse.

D3DSAMP_MINFILTER označava pojavu kada nam više teksela sa teksture zauzima isti pixel na modelu. 

D3DSAMP_MIPFILTER označava primjenu filtriranja kod mip-mapinga. Mip map ćemo sada obradit.

Mip-mapping

Recimo da imate velik model na kojeg ste naljepili teksturu. Ukoliko je taj model vidljiv, te blizu našeg oka, poveća tekstura na modelu opravdava troskove, jer se tekseli poklapaju sa svim pikselima, te model izgleda dobro. No, ukoliko se udaljimo od tog modela, on će izgledati drugačije. U ovom slučaju možemo koristiti i daleko manje teksture nego original. DX nam je u ovom slučaju ponudio jednosatvno rješenje - mip mape.

Na originalnu teksturu, recimo veličine 512x512 se veže lanac istih, ali rezolucijom manjih tekstura. Nakon sto to napravimo, DX automatski koristi novonastalu teksturu. Mip mape se mogu kreirati automatski, no ako vam takav način neodgovara mozete i kreirati svoju vlastitu mip mapu, ali u ovom slučaju spremate je u .dds format.

Primjer kreiranja Mip-mape:

IDirect3DTexture9*pMipMap

 m_pd3dDevice > CreateTexture (256, 256, 5,  0,  D3DFMT_R8G8B8,      D3DPOOL_MANAGED,

&MipMap);

Prvi i drugi parametar nam definiraju visinu i širinu teksture koju učitavamo, dok nam treci paramter definira koliki mip map želimo.

No, ni MipMape nisu savrsene. Prvi problem dolazi da nam treba nekoliko tekstura, no manje rezolucije što povećava memorijske zahtjeve.

Drugi problem dolazi zbog ostrog prijelaza izmedu mip mapa, što posebno dolazi kod ponavljanja tekstura, te većih tekstura (Tomb Raider serijal).

Formati Tekstura

Malo prije sam spomenuo format D3DFMT_R8G8B8, što nam predstavlja format teksture koju želimo učitati ili kreirati. Ovaj format nam govori da se radi o teksturi koja ima 3 komponente - Red, Green, Blue, te da svaka komponenta zauzima po 8 bita, što u konačnici iznosi 24 bita. Dakako, svaki format ima svoje i mane. Recimo teksture u odredenim formatima se nemogu posloziti kao render target.

Najčešće koristeni formati tekstura su:

D3DFMT_A8R8G8B8 -- 32biti format sa 8 bitnim komponentama, alfa, crvena, zelena, plava.

D3DFMT_X8R8G8B8 -  32 bitni format sa 8 bitnim komponentama, crvena, plava i zelena.

d3dfmt_r8g8b8 - 24bitni format sa 8 bitnim komponentama, crvena, plava i zelena.

Sve ove komponente imaju po 8 bytova i imaju pozitivne brojeve, što nam kod recimo bump mapinga neodgovara, jer on treba negativne brojeve. Radi toga imamo i drugačije vrijednosti.

D3DFMT_V8U8 - 16 bitni format sa 8 bitnim komponentama, te U i V komponentama.

D3DFMT_Q8W8V8V8 - 32 bitni format sa 8 bitnim Q, W, V, V, komponentama.

D3DFMT_V16U16 - 32 bitni format sa 16 bitnim U, V komponentama.

Isto tako, nekada nam trebaju teksture koje umjesto cjelobrojnih vrijednosti imaju i vrjednosti sa pomičnim zarezom (floatima), gdje imamo nekoliko vrsta:

D3DFMT_R16F - 16 bitni format sa 16 bitnom crvenom komponentom.

D3DFMT_G16R16F - 32 bitni format sa 16 bitnom crvenom i zelenom komponentom.

D3DFMT_G32R32F - 64 bitni format sa 32 bitnom crvenom i zelenom komponentom.

D3DFMT_A32B32G32R32F - 128 bitni format sa 32 bitniim komponentama. Alfa, plava, crvena. zelena.

 

Cube Texture

Kako bi ubili monotonije linearnih tekstura, imamo i na raspolaganju i cube teksture. To je tekstura koju si mozemo predociti kao kocka na čije su stranice naljepljene normalne teksture.¸Princip je dosta jednostavan,  uzmete vektor smjera koji vam pada na odredeni vertex ili pixel, od tog vektora smjera odredite smjer refleksije uz pomoć normale koju imate na vertexu, te taj novi vektor iskoriste kao index uz pomoć kojeg možete zahvatiti neki piksel na cube teksturi.

Pravilna primjena cube tekstura bi se mogla svesti na par osnovnih koraka: posavljanje svake stranice teksture kao render target, iscrtavanje geometrije okolnog svijeta na svaku stranicu te koristenje tako kreiranje teksture za model. U biti model uzme samo svoj screenshot svoje okoline te onda takav screenshot koristi kao teksturu koja mu omogucuje da vidi svoju okolinu. Postavljanje cube teksture i nije najzahvalnija stvar, te dosta zahtjeva resursa, no cube teksturu mozete kreirati i prilikom pokretanja aplikacije, ili ju kreirati zasebno pa ju učitati kao zasebnu teksturu, uostalom kao i svaku teksturu, ali imajte na umu da DX samo samo sa .dds formatom.

Kasnije ću još pokazati i primjere preko FF Pipelina, te nakon toga to bi trebalo biti to, a od modova zahtjevam sticky :-)

 

Primjer cube texture Primjer cube texture
Evo ide nevjesta preljepa je zaista
Poruka je uređivana zadnji put sri 2.9.2009 16:38 (fabijan654321).
 
3 0 hvala 4
15 godina
protjeran
offline
DirectX Škola

Da ne ulazi u prijasni post, radi preglednosti ovdje ću napisati:

PRIMJER MATERIJALA PREKO FIXED FUNCTION PIPELINE:

D3DMATERIAL9 mat;

mat.Difuse.r =  0.8f;

mat.Difuse.g = 0.8f;

mat.Difuse.b = 0.8f;

mat.Difuse.a = 1.0f;

 

mat.Ambient.r = 0.5f;

mat.Ambient.g = 0.5f;

mat.Ambient.b = 0.5f;

mat.Ambient.a = 0.5f;

 

mat.Specular.r = 1.0f;

mat.Specular.g = 1.0f;

mat.Specular.b = 1.0f;

mat.Specular.a = 1.0f;

 

mat.Emissive.r = 0.0f;

mat.Emissive.g = 0.0f;

mat.Emissive.b = 0.0f;

mat.Emissive.a = 0.0f;

 

m_pd3dDevice->SetMaterial( &mat );

//postavljamo materijal

 

 

PRIMJER SVEJTLA KROZ FIXED FUNCTION PIPELINE

D3DLIGHT9 light;  // svjetlo

ZeroMemory ( &light, sizeoff(light)  );  //  ocistimo strukturu

light.type = D3DLIGHT_DIRECTIONAL;  //  tip svjetla (D3DLIGHT_POINT,  D3DLIGHT_SPOT ili D3DLIGHT_DIRECTIONAL)

 

D3DVECTOR3  vecDir;

vecDir = D3DXVECTOR3 (0.5f,  0.5f,  0.5f);

light.Direction = vecDir;  // kut pod kojim pada svjetlo

light.Difuse.r = 1.0f; boja svjetla

light.Difuse.g = 1.0f;

light.Difuse.b = 1.0f;

light.Difuse.a = 1.0f;

 

m_pd3dDevice->SetLight (  0,  &light );   //

postavimo svjetlo

m_pd3dDevice->LightEnable ( 0,  TRUE );  // i na kraju uključimo ga.

 

Evo ide nevjesta preljepa je zaista
Poruka je uređivana zadnji put sri 2.9.2009 14:14 (fabijan654321).
 
2 0 hvala 3
1
Nova poruka
E-mail:
Lozinka:
 
vrh stranice