Drawing many textured quads at once

Started by
5 comments, last by unbird 10 years, 11 months ago

In my DirectX 11 application, I would like to draw a scene consisting of many textured quads. For the sake of efficiency, my first thought was to use instancing to pull this off in a single draw call - four common vertices and an instance buffer containing transformation matrices to handle positioning of each instance, and an index for which texture to sample from. I had hoped I could do this using a single Texture2DArray resource for storing my collection of textures, but the textures all vary in size (though would share the same format). This does not appear to be possible with a Texture2DArray.

I would really like to avoid a separate draw call for each of these quads. From what I understand there is overhead involved in draw calls that can create a CPU bottleneck, especially considering I would only be drawing two triangles per call.

Anyone have suggestions on the most efficient way to do this?

Advertisement

Can you break up the larger textures in blocks, such that all texture parts are the same size, using multiple quads to act as one quad visually?

Can you break up the larger textures in blocks, such that all texture parts are the same size, using multiple quads to act as one quad visually?

Thanks for the suggestion. It would be possible, but I'm still hoping for a more straightforward solution.

One approach is a so-called texture atlas, i.e. combine all textures into a big one. An example use case is a bitmap font for rendering text. You should find plenty of examples and even tools to generate such atlases (also google "rectangle packing").

Edit: Simpler to implement, but memory wasteful: Stay with the texture array approach and set width and height like the largest of your textures. Pack all other textures e.g. topleft and when drawing make sure the instance hits the correct texcoords.

In both cases you need to change some of your texture coordinates. For the texture array the smaller images no longer use the far corners (1,1) so you have to compute the new values. For the texture atlas you need to compute values that don't all start at (0,0). If you want to do it all in a single draw call this is the best way. Instancing seems incredibly important for performance--I was rendering 100 cubes normally then instanced and I saw a 10x speedup.

Thanks unbird and menohack for your suggestions.The texture atlas may be problematic because these aren't static textures that I can layout into an atlas resource in advance - these textures are first rendered by prior Draw calls and may be redrawn frequently. Basically I am drawing many things to these off-screen textures and then compositing them to the screen as quads, which I would like to do with instancing. I will consider the Texture2DArray suggestion using the largest texture for the dimensions.

This does not necessarily inhibit you from using an atlas. You can render to parts of a texture by using an appropriate quad/transformation or viewport.

But yeah, the array approach is definitively easier.

This topic is closed to new replies.

Advertisement