PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [DX] Wie Koordinaten von Vertizes ändern?


amida maru
2009-12-06, 19:46:14
Hallo erstmal.
Also ich verwende DirectX9 für mein neues 2d game projekt. Erstmal hab ich die VertexBuffer locken - koordinaten ändern - vertexbuffer unlocken gelernt. hab dann gelesen dass das recht langsam ist. dann bin ich auf matrizen umgestiegen mit ner Ortho Matrix:
D3DXMatrixOrthoOffCenterLH(&matOrtho, 0, 800, 600, 0, 1.0f, 10.0f);
m_lpD3DDevice->SetTransform(D3DTS_PROJECTION, &matOrtho);
m_lpD3DDevice->SetTransform(D3DTS_WORLD, &matIdentity);
m_lpD3DDevice->SetTransform(D3DTS_VIEW, &matIdentity);


ok dann meine Sprite klasse die SetupQuad methode die ruf ich beim initialisieren EINMAL auf und beweg sie dann mit matrizen und zwar in der funktion Blit:


void Sprite::SetupQuad()
{
pGameService->GetD3DDevice()->CreateVertexBuffer(sizeof(GameService::VERTEX) * 6, NULL, pGameService->GetVertexFormat(), D3DPOOL_MANAGED, &m_pVertexBuffer, NULL);

m_pVertices = NULL;

m_pVertexBuffer->Lock(0, 6 * (sizeof(GameService::VERTEX)), (void**)(&m_pVertices), 0);

m_pVertices[0].color = 0xffffffff;
m_pVertices[0].x = 0.0f;
m_pVertices[0].y = 0.0f;
m_pVertices[0].z = 1.0f;
m_pVertices[0].u = 0.0f;
m_pVertices[0].v = 0.0f;

m_pVertices[1].color = 0xffffffff;
m_pVertices[1].x = 1.0f;
m_pVertices[1].y = 0.0f;
m_pVertices[1].z = 1.0f;
m_pVertices[1].u = 1.0f;
m_pVertices[1].v = 0.0f;

m_pVertices[2].color = 0xffffffff;
m_pVertices[2].x = 1.0f;
m_pVertices[2].y = 1.0f;
m_pVertices[2].z = 1.0f;
m_pVertices[2].u = 1.0f;
m_pVertices[2].v = 1.0f;

m_pVertices[3].color = 0xffffffff;
m_pVertices[3].x = 1.0f;
m_pVertices[3].y = 1.0f;
m_pVertices[3].z = 1.0f;
m_pVertices[3].u = 1.0f;
m_pVertices[3].v = 1.0f;

m_pVertices[4].color = 0xffffffff;
m_pVertices[4].x = 0.0f;
m_pVertices[4].y = 1.0f;
m_pVertices[4].z = 1.0f;
m_pVertices[4].u = 0.0f;
m_pVertices[4].v = 1.0f;

m_pVertices[5].color = 0xffffffff;
m_pVertices[5].x = 0.0f;
m_pVertices[5].y = 0.0f;
m_pVertices[5].z = 1.0f;
m_pVertices[5].u = 0.0f;
m_pVertices[5].v = 0.0f;

m_pVertexBuffer->Unlock();

pGameService->GetD3DDevice()->SetStreamSource(0, m_pVertexBuffer, 0, sizeof(GameService::VERTEX));

}


void Sprite::Blit(int x, int y)
{
D3DXMATRIX matTranslation;
D3DXMATRIX matScaling;
D3DXMATRIX matTransform;


D3DXMatrixScaling(&matScaling, (float)m_Width, (float)m_Height, 1.0f);



D3DXMatrixTranslation(&matTranslation, (float)x, (float)y, 0.0f);


matTransform = matScaling * matTranslation;


pGameService->GetD3DDevice()->SetTransform(D3DTS_WORLD, &matTransform);
pGameService->GetD3DDevice()->SetTexture(0, m_pTexture);
pGameService->GetD3DDevice()->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2);

}

Ein Programmierfreund sagt es ist blöd für jedes objekt immer ein renderaufruf zu machen. stimmt das? er sagt ich soll den vertexbuffer locken die ganze koordinaten reinschreiben und dann ein renderaufruf machen. aber ich versteh das nich ganz? was ist jetzt der richtige weg? und kann man die texturkoordinaten u, v auch mit matrizen ändern oder nur durch locken des vertexbuffers?

lg Tibo

Gast
2009-12-06, 23:30:51
Performancefragen:
http://tomsdxfaq.blogspot.com/

Matrixfragen, Texturkoordinatenfragen:
http://blog.wolfire.com/2009/07/linear-algebra-for-game-developers-part-1/

Coda
2009-12-06, 23:37:50
Rufst du das SetupQuad etwa pro Zeichenaufruf auf? Das SetStreamSource sieht nämlich danach aus.

Gast
2009-12-07, 00:34:50
Dein Problem ist, dass du je Sprite-Blit die Matrix und die Textur setzen
musst (eine Matrix und eine Textur je Sprite).

Statt dessen kannst du zuerst die Texturen in eine grosse Textur (oder
wenige grosse Texturen) packen und deine Sprite-Koordinaten entsprechend
setzen (entweder im Vertex-Buffer oder per Texture-Transformationsmatrix),
das spart dann schonmal den SetTexture-Aufruf je Sprite.

Für die Koordinatentransformation kannst du einen weiteren Buffer mit
Koordinaten (+ evl. Tex-Koordinaten,Rotationswinkel) anlegen. Dafür
schreibst du einfach einen Vertexshader, der deine Vertices und die
Koordinaten einliest und entsprechend transformiert.

Beides zusammen ergibt dann für alle Sprites nur noch einen Aufruf
zum Zeichnen und einen Lock-Vorgang fürs ändern der Koordinaten.
Für Details hilft evtl. noch "IDirect3DDevice9::SetStreamSourceFreq"
zum Einsparen div. Bufferdaten.

Viel Spass

amida maru
2009-12-07, 18:21:02
ne code ich hab bisher es so gemacht dass jedes sprite einen eigenen vertexbuffer hat das ändere ich aber. meine frage ist wenn ich eine größere Textur hab wo zb 5 spielfiguren(inklsuvie animation) drin ist dann soll ich dafür einen vertexbuffer anlegen? bzw für was soll ich vertexbuffer anlegen. also bisher will ich es so machen für jede map(die aus tiles besteht 32*32 pixel) ein dynmischen vertexbuffer. und für alle sprites(beweglichen mit animationen) ein dynamischen vertexbuffer und für alle gameobjekte(die sich net bewegen) einen statischen vertexbuffer^^

Gast
2009-12-07, 22:52:01
Lege einen VertexBuffer B1 für das Sprite-Quad an (mit Koord. (0,0)..(1,1)).
Ein weiterer VertexBuffer B2 enthält dann je Sprite eine Struktur mit
Position (z.B. SpriteCenter), Texture-Offset (muss für Animationen
geändert werden und evtl. Scale- und Rotation-Infos etc. Dazu kommt noch
eine grosse Texture, die in Tiles unterteilt ist (für Animation: mehrere Tiles
je Sprite).
Der nächste Schritt ist dann, per IDirect3DDevice9::SetStreamSourceFreq
Buffer B1 nur einmal und B2 immer wieder zu streamen (schau am Besten
in der SDK-Doku nach, ist nicht so kompliziert wie sichs anhört).
Dann brauchst du nur noch einen entsprechenden VertexShader, der je
Vertex die Koordinate (aus B1) und die Position,Texture-Offset etc. (aus B2)
liest und transformiert (Pos+Koord => neue Koord, TexKoord+0.5*Koord =>
neue TexCoord etc.).
Die Aufgabe deiner Sprite-Klasse liegt dann nur noch im Verwalten der
TextureTile-Offsets je Sprite und das Änden von B2 (z.B. Position und
Grösse, Texture-Offset-Anderung bei Texture-Animationen).

Viel Spass

Coda
2009-12-08, 00:21:51
ne code ich hab bisher es so gemacht dass jedes sprite einen eigenen vertexbuffer hat das ändere ich aber.
Was soll dann das SetStreamSource?

amida maru
2009-12-08, 13:44:55
ja wenn ich nur ein vertexbuffer hab muss icuh natürlich den grad aktuellen buffer mit setstreamsource "aktivieren" logisch. also ich kann keine shader...

Coda
2009-12-08, 15:39:55
Wieso nur einen Vertexbuffer? Ich dachte du hättest mehrere ;)

amida maru
2009-12-08, 16:18:37
ja wir reden aneinander vorbei. zum testen hab ich einen pro sprite verwendet aber habs ja jetzt geändert :)
aber trotzdem danke an alle.

peace and love
Tibo

Gast
2009-12-08, 17:27:25
Schau dir aber trotzdem in der SDK-Doku die Shader-Programmierung an.
Ist in der aktuellen SDK unter HLSL die Abschnitte zu DirectX9 (bei mir
2 Seiten). Ist auf jeden Fall eleganter und flexibler als Methodenaufrufe wie "m_lpD3DDevice->SetTransform" .., die ja je Sprite aufgerufen werden müssen.


Gruss