Batching 2D quads?

Started by
3 comments, last by MasterWorks 17 years, 11 months ago
Hi there, I'm making a 2D display engine using textured quads. A texture is drawn using a D3DPT_TRIANGLEFAN DrawPrimitive. However, the situation may arise that many (a few hundred) small, identical textures need to be drawn on to the screen at once. Currently the engine starts to slow down quite a bit in this situation, presumably because there is a DrawPrimitive for each of the objects drawn, and this would involve seperately uploading vertices to the graphics card, which is bad. For lines and points and such, you can effectively batch them by listing them all in one vertex buffer and sending them in one go, which greatly improves performance. Is there any similar way of doing this with textured quads? Adding extra vertices will just add to the same triangle fan with my current code. Any help appreciated.
Construct (Free open-source game creator)
Advertisement
I'd suggest using indexed triangle lists.
Can you point me in the direction of a good article/tutorial on index buffers?
Construct (Free open-source game creator)
You can always use D3DXSPRITE, but if you want to go a little deeper than that...

I'd create a list of texture ids on coordinates (ie. int world_array[16][16]).

There are several ways you can sort the ids, but I'd start with just creating the quads in the vertex/index buffer when it comes across the respective id.
Don't forget to count the amount of hits on the id because you don't want to render a quad with the incorrect id.
EX:
// lock vertex buffer
for(int z=0; z<max_ids; z++)
for(int x=0; x<16; x++)
for(int y=0; y<16; y++)
{
if (world_array[x][y] == z)
{
count_id[z]++;

// create quad in vertex buffer
}
}
// unlock vertex buffer

// lock index buffer
for(int x=0; x<16; x++)
for(int y=0; y<16; y++)
// create indices

// unlock index buffer

Use DrawIndexedPrimitive w/ D3DPT_TRIANGLELIST for each texture using count_id[tex_id] as the primitive counter times two (quads are two tris).

Use the list because a fan may create strange looking primitives on the screen, and because not all of those primitives are going to be in a row/column. It may also create the primitives with the incorrect id.
The most important thing you can do is put your small textures together into a big graphics file (.PNG, .TGA, .JPG, .BMP, etc.) so that you don't have to change to a new texture anywhere near as often. Just use texture coordinates to pluck out the sprite you need.

The suggestion of using indexed triangle lists is excellent. Then you can render multiple sprites in one batch, even if they share no vertices and are completely disjoint, so long as they DO share a texture (hence the importance of combining them).

For optimal speed look into using dynamic vertex and index buffers. They are FAR more efficient for sprite-type 2D engines because you can change the vertices every frame (for particles position, animation, color, size, etc.) and still get excellent performance. Research the proper usage of the locking flags as they can be tricky and you have to get it right to get the speed.

This topic is closed to new replies.

Advertisement