Desenarea particulelor folosind poligoane pătrate

Revenind la jocul cu monștri, puteți folosi particule pentru a reprezenta mașini mici care se deplasează de-a lungul străzilor orașului. Un simplu poligon pătrat texturat (folosind billboarding) va fi suficient pentru aceste mașini, dar dacă în loc să utilizați o plasă tridimensională? Ar fi nevoie doar de vizualizarea mai multor poligoane suplimentare în fiecare cadru și, credeți-mă, efectul acestor mașini mici care se deplasează în jurul orașului ar costa un timp suplimentar de vizualizare.

Dacă nu atingeți vizualizarea ochiurilor, majoritatea particulelor pe care le desenați vor fi alcătuite din poligoane pătrate. Le puteți desena în moduri diferite, dar în această carte vă voi arăta trei. Prima metodă de desenare a particulelor este probabil cea mai simplă, dar după cum veți vedea în curând, aceasta are dezavantajele sale.

Desenarea particulelor este la fel de ușoară ca și poligoanele de desenare, deoarece o particulă este doar un poligon pătrat, cu textură și pătrată. În Fig. 12.4 arată apariția a două triunghiuri care sunt folosite pentru a crea particule. În această figură am arătat o particulă având o dimensiune de 10 unități.

Fig. 12.4. O particulă având o dimensiune de 10 unități are o lungime de 5 unități în direcțiile axelor x și y

Pe lângă coordonatele de vârf utilizate în desenarea particulelor,

aveți nevoie de încă câteva lucruri. În primul rând, aveți nevoie de o textură folosită pentru a îmbunătăți aspectul particulei. Dacă această textura este fum, o grămadă de lumină sau o persoană înspăimântată, trebuie să stocați o imagine în obiectul texturii. În plus față de texturi, poligoanele au nevoie de informații despre coordonatele de textură pentru aplicarea unei texturi la un poligon.

Pentru simplitate, voi folosi doar o textura pentru fiecare tip de particula din acest capitol. Cu alte cuvinte, dacă există particule de fum și foc, voi încărca două texturi. Orice instanță a oricărei particule își va folosi textura proprie atunci când este redată. Poate că doriți să combinați toate texturile de particule într-una, pentru a îmbunătăți particulele.

Următorul lucru de care aveți nevoie pentru a crea datele poligonului pentru particule este componenta difuză a culorii. Abilitatea de a schimba culoarea particulelor în timpul rulării este foarte utilă, deoarece schimbările de culoare pot reprezenta diferite cicluri de viață ale particulelor. De exemplu, focul se răcește încet și își schimbă culoarea în timp ce se îndepărtează de sursa de căldură. În loc să utilizați mai multe texturi pentru a reprezenta diferite niveluri de încălzire, puteți utiliza aceeași textură și pur și simplu schimbați culoarea împrăștiată a particulei.

Ultimul lucru de care aveți nevoie este dimensiunea particulelor. În general, particulele pot avea orice dimensiune, de la un mic punct de praf la un meteor care zdrobește Pământul. Pentru a determina dimensiunea particulelor, trebuie să selectați dimensiunile particulelor folosind aceleași coordonate mondiale care utilizează ochiurile 3D.

Să presupunem că doriți ca particula să fie de 20 de unități și de 50 de unități înălțime. Această dimensiune se aplică numai axelor x și y (deoarece, de fapt, particula este un obiect plat, care este întotdeauna îndreptat către spectator). Când se creează o particulă, centrul său este situat la originea lumii. Folosind dimensiunile de particule, puteți crea noduri reprezentând unghiurile. Aceste noduri sunt localizate folosind dimensiunile particulelor împărțite în jumătate ca deplasare. De exemplu, o particulă de dimensiuni 20x50 se află între -10 și 10 pe axa x și de la -25 la 25 pe axa y.

Asta e totul despre asta, acum trebuie să ai suficiente informații pentru a începe să desenezi particule! Pentru a rezuma: este necesar să aibă mărimea și coordonatele vârfurilor particulei (folosind dimensiunea ca bază), coordonatele texturii și componenta de culoare împrăștiată pentru fiecare vârf. Mergeți mai departe și îmbinați toate aceste componente într-o structură de vertex, așa cum am făcut aici:

D3DXVECTOR3 vecPos; // Coordonatele topului de particule D3DCOLOR Diffuse; Culoare împrăștiată

float u, v; // coordonatele texturii> sVertex;

#define VERTEXFVF (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1)

Folosind structura de vertex și FVF, puteți crea un tampon de vertex mic care conține suficiente noduri pentru a desena o particulă. Pentru o particulă sunt folosite două triunghiuri, ceea ce înseamnă că trebuie să creați șase vârfuri (trei pentru fiecare triunghi). Folosind o bandă de triunghiuri, puteți reduce numărul de vârfuri la patru.

Puteți crea un tampon de vârf utilizând următorul cod:

IDirect3DVertexBuffer9 * pVB = NULL; pDevice-> CreateVertexBuffer (4 * sizeof (sVertex), \

D3DUSAGE_WRITEONLY, \ VERTEXFVF, D3DPOOL_DEFAULT, \ pVB, NOLL);

După ce creați un tampon de vertex (acesta este creat o dată în program), îl puteți umple cu date despre particule. Să presupunem că doriți să desenați o particulă care are o dimensiune de 10 unități (atât în ​​direcția x, cât și în direcția y), folosind întreaga suprafață a texturii având o culoare albă. Pentru a face acest lucru, trebuie să utilizați următorul cod:

// Size = dimensiunea particulelor, în acest caz 10.0 float Size = 10.0;

// Obțineți dimensiunea, împărțită la jumătate, pentru a seta coordonatele verticalelor float HalfSize = Size / 2.0f;

// Blocheaza tamponul vertex si umple-l cu date vertex sVertex * Vertex = NULL;

pVB-> Lock (0, 0, (void **) Vertex, 0);

// Colțul din stânga sus, numărul de vârf 0

pVB [0] .vecPos = D3DXVECTOR3 (-Size, Dimensiune, 0.0f); pVB [0]. Diffuse = D3DCOLOR_RGBA (255,255,255,255); pVB [0] .u = 0.0f; pVB [0] .v = 0.0f;

// Colțul din dreapta sus, numărul vertexului 1 pVB [1] .vecPos = D3DXVECTOR3 (Dimensiune, Dimensiune, 0.0f); pVB [1]. Diffuse = D3DCOLOR_RGBA (255,255,255,255); pVB [1] .u = 1,0f; pVB [1] .v = 0.0f;

// Colțul din stânga jos, numărul vertexului 2 pVB [2] .vecPos = D3DXVECTOR3 (-Size, -Size, 0.0f); pVB [2]. Difuză = D3DCOLOR_RGBA (255,255,255,255); pVB [2] .u = 0.0f; pVB [2] .v = 1,0 f;

// Colțul din dreapta jos, numărul vertexului 3 pVB [3] .vecPos = D3DXVECTOR3 (Dimensiune, -Size, 0.0f); pVB [3]. Diffuse = D3DCOLOR_RGBA (255,255,255,255); pVB [3], u = 1,0 f; pVB [3], v = 1,0 f;

// Deblocați tamponul de vârfuri

Acum tamponul de vertex este gata pentru vizualizare. Cu toate acestea, există o subtilitate mică. Veți observa că coordonatele vârfurilor au poligoane în centrul coordonatelor lumii tridimensionale, extinzându-se în direcția axelor x și y. Deoarece punctul de vedere poate fi oriunde în lume, trebuie să aranjați poligoanele folosind transformarea lumii înainte de redare.

Este, de asemenea, necesar să rotiți poligoanele astfel încât să vizeze spectatorul, care, după cum vă amintiți, este scopul panourilor. Trebuie să calculați conversia panoului pentru a roti poligoanele

pentru spectator. Folosind această transformare, adăugați coordonatele particulei

în locul unde ar trebui să fie desenat (în coordonatele lumii).

Avertizare. Utilizarea funcției GetTransform pentru conversia Direct3D zamedlyaetrabotu puternic și nu este întotdeauna posibil. Cel mai bun păstrat globalnyepreobrazovaniyamira, vidaiproektsii, kotoryemozhnopotomispolzovat.Odnako pocăință va urma o cale rea și va folosi în scopuri vuchebnyh GetTransform.

Pentru a crea o transformare panou este necesară pentru a obține o conversie de tip matrice și calculează matricea inversă (schimbând astfel ordinea conținute în acesta transformări asupra revers) folosind funcția D3DXMatrixInverse, așa cum se arată aici:

// Obțineți matricea de transformare a vizualizării și inversați-o cu D3DXMATRIX matView;

pDevice-> GetTransform (D3DTS_VIEW, matView); D3DXMatrixInverse (matView, NULL, matView);

Folosind transformarea inversă va permite particulelor să se rotească în partea de sus într-o direcție opusă direcției de forma, aliniind astfel coordonatele privitorului. După ce a primit transformata inversă a formei trebuie să fie adăugate direct la locația de coordonate particulelor sale în lumea tridimensională. Puteți face acest lucru prin salvarea coordonatele x, y și z în elementele _41, _42 i_43 respectiv doar calcula matricea de transformare inversă și stabilirea matricei de transformare care rezultă ca o transformare globală.

/ / Pune ParticleXPos, ParticleYPos și ParticleZPos conțin lume

// coordonate ale particulei desenate. Adăugați coordonatele particulei trasate matView._41 = ParticleXPos;

matView._42 = ParticleYPos; matView.43 = ParticleZPos;

// Setați matricea rezultată ca transformare lume pDevice-> SetTransform (D3DTS_WORLD, matView);

Odată ce ați instalat matricea de transformare globală, puteți vizualiza poligoanele. Pentru ca particulele să fie combinate cu scena, trebuie să vă asigurați că utilizați testarea z-tampon și alfa. Utilizarea tamponului z asigură faptul că particulele sunt afișate corect în scenă, iar testarea alfa asigură faptul că părțile transparente ale texturii particulelor nu sunt desenate (permițându-vă să vedeți geometria rămasă prin aceste părți transparente). De asemenea, puteți activa amestecarea alfa dacă doriți să creați anumite efecte de amestecare.

Dacă ați sări peste setarea z-buffer (ar fi trebuit să o faceți mai devreme), puteți să activați alfa-test și amestecarea alfa după cum urmează:

// Activați testarea alfa

pDevice-> SetRenderState (D3DRS_ALPHATESTENABLE, TRUE); pDevice-> SetRenderState (D3DRS_ALPHAREF, 0x08); pDevice-> SetRenderState (D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);

// Activare alfa amestecare (tip simplu adăugare) pDevice-> SetRenderState (D3DRS_ALPHABLENDENABLE, TRUE); pDevice-> SetRenderState (D3DRS_SRCBLEND, D3DBLEND_SRCCOLOR); pDevice-> SetRenderState (D3DRS_DESTBLEND, D3DBLEND_DESTCOLOR);

În ceea ce privește testarea alfa, am ales să folosesc regula de comparare mai mare sau egală. Acest lucru înseamnă că, dacă particulele de pixeli textura au o valoare alfa mai mare sau egală cu 8, atunci când sunt vizualizate, în caz contrar, ele vor fi omise. Folosind testul alfa este necesar funcții D3DXCreateTextureFromFileEx utilizați pentru a încărca texturi, setarea modului de culoare folosind canale alfa (cum ar fi D3DFMT_A8R8G8B8), și tasta neagră și opacă de culoare (D3DCOLOR_RGBA (0,0,0,255)), așa cum se arată în următoarea bucată de cod:

D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, D3DX_DEFAULT, DEFAULT D3DX, D3DCOLOR_RGBA (0,0,0,255), NULL, NULL, pTexture);