views:

829

answers:

4

I am new to DirectX and I am trying to draw two rectangles in one scene using D3DPT_TRIANGLESTRIP. One Rectangle is no problem but two Rectangles is a whole different ball game. Yes i could draw them using four triangles drawn with the D3DPT_TRIANGLELIST primitive type. My curiosity is on the technic involved using D3DPT_TRIANGLESTRIP. Parts of the code i am using for one Rectangle using D3DPT_TRIANGLESTRIP is as follows:

CUSTOMVERTEX recVertex[] = {
    {  10.0f,  10.0f, 0.10f, 1.0f, 0xffffffff, }, // x, y, z, rhw, color
    { 220.0f,  10.0f, 0.10f, 1.0f, 0xffffffff, },   
    {  10.0f, 440.0f, 0.10f, 1.0f, 0xffffffff, },   
    { 220.0f, 440.0f, 0.10f, 1.0f, 0xffffffff, },
}; 

if( FAILED( g_pd3dDevice->CreateVertexBuffer( 4 * sizeof( CUSTOMVERTEX ),
               0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL ) ) )
{
    return E_FAIL;
}

More vital code...

VOID* precVertex;    
if( FAILED( g_pVB->Lock( 0, sizeof( recVertex ), ( void** )&pGameField, 0 ) ) ) 
{
return E_FAIL; 
}
 memcpy( precVertex, recVertex, sizeof( recVertex ) );

then Render like so...

g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof( CUSTOMVERTEX ) );
g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );

Based on this model I could easily duplicate the code change the x and y values on the Custom Vertex and create another vertex buffer and it would work.

Personally i feel this is not the best way to go especially considering a situation when i have to draw say 100 rectangles or something like that. The thing is, I don't have other ideas. So my question is, what is the most efficient way to draw two Rectangles with D3DPT_TRIANGLESTRIP? Also is there a possible way of duplicating and transforming the current rectangle?

+1  A: 

Add the four vertices for the second rectangle to the vertex buffer, then call DrawPrimitive twice.

g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof( CUSTOMVERTEX ) );
g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );
g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 4, 2 );
avakar
Ok this is what i was actually looking for. Its given me great insight. only one thing remember to change the 4 to 8 since we now have 8 vertices in the CreateVertexBuffer function.
Steve Obbayi
+1  A: 

You could extend recVertex to 8 points. This is a common technique. 3D hardware designed to work exactly in such mode. Check out this tutorial for instance.

If you want to draw 100 (I assume that means "a huge number" in context of question) rectangles you should consider using meshes.

Kirill V. Lyadvinsky
+3  A: 

The most efficient way is to use an indexed draw and then to repeat indices in between the 2 rectangles.

ie indices 0, 1, 2, 3, 3, 4, 4, 5, 6, 7 produces the following triangles from triangle stripping

0, 1, 2 - 1, 2, 3 - 2, 3, 3 - 3, 3, 4 - 3, 4, 4 - 4, 4, 5 - 4, 5, 6 - 5, 6, 7

the triangles 2, 3, 3 - 3, 3, 4 - 3, 4, 4 and 4, 4, 5 all have zero area and will be discarded very early on the graphics card. This way you get 4 triangles rendered in one call to DrawIndexedPrimitive.

Of course that means you are sending in 10 indices. You may as well just send in 12 indices and draw both rectangles as 4 triangles in a tri list. When using indexed drawing you'll find that the hardware keeps track of what vertices it has already transformed so that it doesn't have to bother again.

ie if you define your index buffer as

0, 1, 2, 3, 0, 2, 4, 5, 6, 7, 4, 6

and you have a post transform cache of at least 4 vertices (Pretty much every graphics card has a significantly larger post transform cache, The GeForce 3 certainly did!) then you can see that both triangles will be rendered and yet each vertex will only be transformed once. Counter-intuitively on any post DX8 hardware (ie any DX9 or 10 hardware) you'll find that the use of this post transform cache and extra simplicity of triangle lists means that you'll actrually get BETTER performance from a triangle list than a triangle strip.

So in summary in answer to the question "So my question is, what is the most efficient way to draw two Rectangles with D3DPT_TRIANGLESTRIP?" the answer is to draw is a D3DPT_TRIANGLELIST and stop worrying about it :)

Goz
A: 

It's generally best to batch up geometry into larger indexed vertex buffers and call the appropriate draw functions with the correct offsets into the buffer for each 3D object. Remember hardware doesn't view your objects as separate entities, it only cares about vertex/index buffers, textures, shader programs and assorted state. Your job is to feed it all to the hardware in an optimum manner and batch up a reasonable amount of drawing tasks per frame.

For tiny little geometry and fixed function like this you should definitely be slapping the whole lot into a single buffer.

Captain Lepton