direct 3d design questsions

Started by
21 comments, last by superpig 15 years, 11 months ago
1) Which of these two methods for drawing basic shapes(eg a rectangle for a sprite) is better: a) Have a static vertex that stores all the basic infomation for triangles, rectangles, etc and use "D3dDevice->SetTransform(D3DTS_WORLD, &Matrix);" to draw these where I want eg:

//...vertex buffer populated with vertexes for a 200*200 sqaure around 0,0

//draw a rotated square in the centre of a 800*600 screen
D3DXMATRIX Rot, Trans;
D3DXMatrixTranslation(&Trans, 400,300,0);
D3DXMatrixRotationZ  (&Rot  , (float)DegToRad(45));
//rotate and THEN translate
D3dDevice->SetTransform(D3DTS_WORLD, &Rot*Trans);

D3dDevice->SetStreamSource(0, VextexBufferPrim, 0, sizeof(D3dVertex));
D3dDevice->SetFVF(D3dVertex::FVF);
D3dDevice->DrawPrimitive(D3DPT_TRIANGLEFAN, RectOffset, 2);
b) Use a dynamic vertex buffer to "directly" draw the shapes

//draw a rotated rectangle in the centre of a 800*600 screen
D3dDevice->SetStreamSource(0, VextexBufferDynamic, 0, sizeof(D3dVertex));
D3dDevice->SetFVF(D3dVertex::FVF);
D3dVertex* vertices;
VextexBufferDynamic->Lock(0, 0, (void**)&vertices, D3DLOCK_DISCARD);
vertices[0] = D3dVertex(400,250, 2, cWhite, 0,0);
vertices[1] = D3dVertex(450,300, 2, cWhite, 1,0);
vertices[2] = D3dVertex(400,350, 2, cWhite, 1,1);
vertices[3] = D3dVertex(350,300, 2, cWhite, 0,1);
VextexBufferDynamic->Unlock();
D3dDevice->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);
2)Are buttons and stuff on in game menus generaly implemented with winAPI or by drawing the buttons with Direct3D and using custom code to check if the button has been cliked on etc?
Advertisement
1) Definitely a). If you can get away with using transformation matrices, then do it. Making dynamic vertex buffers work well involves being very careful about how and when you lock your buffers, in order to avoid a performance hit.

2) Usually the GUI is custom. Making the Win32 controls work in fullscreen D3D apps can be a pain from a performance standpoint, and most games want their UI to fit with their overall "look" and feel.

[Edited by - MJP on May 16, 2008 4:24:45 PM]
OK with a is there a way to use a diffrent colour (say I have a grey scale sprite I want to use for the red and the blue team or will I need 2 sets in the buffer, one for each colour?
Quote:Original post by Sync Views
OK with a is there a way to use a diffrent colour (say I have a grey scale sprite I want to use for the red and the blue team or will I need 2 sets in the buffer, one for each colour?
Assuming you're not using shaders, you can do the following:
DWORD dwColor = D3DCOLOR_XRGB(255, 0, 0); // RedpDevice->SetRenderState(D3DRS_TEXTUREFACTORP, dwColor);pDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);pDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);pDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TFACTOR);

That sets the "TFactor" stage to the colour you want to use, and then modulates the texture colour with that colour.
Is it practicle to have lots of smaller buffers (eg one for each object type) rather than having one large one or does that really start to hit proformance when switching between serval diffrent buffers during rendering?
Quote:Original post by Sync Views
Is it practicle to have lots of smaller buffers (eg one for each object type) rather than having one large one or does that really start to hit proformance when switching between serval diffrent buffers during rendering?
The number of buffers doesn't matter so much, it's the number of draw calls you make that does. You shouldn't be making more than 500 DrawPrimitive (Or DrawIndexedPrimitive) calls per frame or so, and putting more objects into one vertex buffer means you can draw multiple objects in one call.

However, for simplicity it's perfectly fine to stick with one vertex buffer per object. But if you find you need more performance, you'll want multiple objects per buffer.
Ok. Before I start doing any code I just want to check this plan is a good one-

-I'm making a basic 2d space shooter just to learn how the basic aspects of Direct3D work (2d cause I fail at making models but can draw half decent sprites lol).

-The current plan is to call DrawPrimitive/SetTexture for every instance of each object. I can only see two ways of doing this and this seems the better of the two.
a)Rebuild the vertex buffer everyframe doing all the transformations myself rather than with matrixes so every instance is in the buffer and can be drawn at once - seems a bad idea to me
b)Have a vertex buffer containing the vertices for that object and call DrawPrimitive for each intance with apporiate transform matrix each time - Alot of DrawPrimitive calls but I suppose it's better than doing all the maths on the CPU and rebuilding the entire buffer every frame
Quote:
and putting more objects into one vertex buffer means you can draw multiple objects in one call.

I only see the above two methods. This seems like a method c but I have no idea how it's meant to work :(

-Background objects with be batched into static buffers of all the same texture (So everything with the star texture, then everything with the blueplanet texture). This can be done at the game start and will just need a few DrawPrimitive calls each frame

Few other points:
If I call DrawPrimitive on a set of vertexes with a transform matrix that is clearly out of the view (eg the view is 800*600 from 0,0 and the matrix translates the vertexes by 2000,5000 from the origin) will DirectX just discard it then or should I check the location of the object myself and not call the DirectX functions at all if it's clear the object is completly offscreen?
Any particular reason why you don't want to use ID3DXSprite for this? It will handle batching of sprites for you.

Quote:Original post by Sync Views
Few other points:
If I call DrawPrimitive on a set of vertexes with a transform matrix that is clearly out of the view (eg the view is 800*600 from 0,0 and the matrix translates the vertexes by 2000,5000 from the origin) will DirectX just discard it then or should I check the location of the object myself and not call the DirectX functions at all if it's clear the object is completly offscreen?


The vertices will get transformed on the GPU, and will be clipped when they're determined to be off-screen. It's better if you can cull that quad yourself, as you'll save yourself the time of a DrawPrimitive call.

Quote:
Any particular reason why you don't want to use ID3DXSprite for this? It will handle batching of sprites for you.

Once ive got something working I intend to start using 3D grafics which a mate of mine said he woould make IF I had a game built to use them in, with an angled view for the game rather than a plain top down view (eg like space empires V combat uses). I'm still going to need to solve the same problems then only about how best to render lots of small models rather than small sprites...

Anyways Ive got the sprite stuff working now by having a 1*1 quad around 0,0 in the vertex buffer and transforming it as needed. The question now is about drawing stuff that I can't see a way to "predefine".

1)For beam lasers I want the texture to repeat along the quad between the start and end. This means the u,v's need to be diffrent pretty much every frame though.
2)Drawing line lists. I can't really see a way to transform a list of say 11 vertexs to get my line to follow the right path.

Is dynamic buffers the way to go here and just checking if I actauly need to rebuild them before doing so (eg if any of the data there built from has changed) the way to go for these things?

EDIT: I'm still not sure what the best way of reducing the number of calls is:
a)batch everything using the same texture into one dynamic buffer doing the world transforms myself and drawing the whole lot with a single DrawPrimitive call
b)Use the static vertex buffer and do everything with a ton of DrawPrimitive calls (eg one for every sprite because they need diffrent transforms...)

[Edited by - Sync Views on May 17, 2008 4:14:03 AM]
So am I basicly stuck with using DrawPrimitive once for every texture in every object then or is there some way to batch several objects each with there own transform matrix?

This topic is closed to new replies.

Advertisement