Jump to content
  • Advertisement
Sign in to follow this  
gfxCahd

Spritebatching

This topic is 2134 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I am currently trying to implement a Spritebatch class for use with Direct3D 10 (through SharpDX). It's just meant as an easy way to do my 2D UI drawing, though of course any speed increases are welcome. As far as I understand the goals are:

1) As little data sent to the GPU as possible

2) As few Draw calls on the GPU as possible.

 

Now, as this is just about 2D rendering, I can acomplish goal 1 by using instancing (Create one quad in a vertex buffer, and use a second buffer for the specific data per sprite (transform, color etc...). Would using a geometry shader to expand a single vertex to a quad offer any advantage? Wouldn't it just incure GS overhead for the benefit of storing just 1 vertex instead of 4? I see people using it for billboarding but I fail to see the advantage it offers...

 

Now 2 is the tricky part. All the elements have the same geometry, and by using the vertex shader I can manipulate it to properly place the quad. But they also require the same texture if they are to be drawn in a single draw call. Now, If they all had the same dimensions, I could use a texture2Darray, but this certanly isn't the case with UI elements. A texture atlas is another choice, but since I want to support various display resolutions (i.e. scale up/down the texture), I need mipmapping, and mipmapping with texture atlases leads to color bleeding.

 

Just using a texture atlas and adding some pixel gutters seems to be the norm , but there is something missing here... Text.

 

Unless I use my own bitmap font engine, and add the fontbitmap to the same atlas, plus take care of drawing the text "myself" with the aforementioned quad (don't forget kerning unless I want monospaced fonts).. oh, and bitmap fonts look like crap anyway when scaled... then there is no point in even trying to "batch" the drawing of UI textures, since there is always going to be a bunch of text drawing calls interspaced between them. Either everything is in the atlas, or if I use ID3DXFONT10, then no point in bothering.

 

Now, I won't be sure unless I implement and profile the various algorythms, but am I off the mark on any of the aforementioned? Maybe just making a simple spritebatch without expecting too much from the "batching" aspect is the way to go, since it will only offer a (by way of pulling a number out my *ss) 20-30% reduction in draw calls, for something that really doesn't have that many calls to begin with (i.e. the UI).

Edited by gfxCahd

Share this post


Link to post
Share on other sites
Advertisement


1) As little data sent to the GPU as possible

... per frame, not during initialization, and since most sprite data is sent during a separate initialization, or a one-time step that you don't repeat every frame, you don't have to worry about the size of the data.


2) As few Draw calls on the GPU as possible.

... also, per frame.

 

You really should learn to separate your work into these two steps:

1) initialization,  where you load up all your resources into the GPU - here, you can freely send any amount of data, and especially the one quad you use for instancing, is no big deal... sending the quad one time and then instancing it is probably faster for the GPU (like you said, it takes less GS processing time than sending a position and expanding it from the GS), but you won't have to worry about this if you jsut send the vertices for teh quad once...

2) per-frame, where you only make calls to the appropriate minimum set of D3D fucntions that do the rendering... anything that doesn't have to do with rendering goes into the initialization step

To that end, your Spritebatch class should probably have two methods: Init, and Render.

 

For 2), you seem to imply that all your UI elements use pre-rendered, static textures, so a texture atlas is your best bet.

Mipmapping does not cause color bleeding - the sampling algorithm for mips is clearly defined, so it doesn't introduce any artifacts. The color bleeding artifacts are usually introduced at design time, by the different resizing algorithms used to create the mips from the original image, or by non-standard graphics card settings (like Nvidia's Antialiasing setting). You should use texture gutters if you want to make sure you don't get sampling artifacts when the non-standard graphics settings are used.

 

For the bitmap fonts approach of rendering text, you don't have to use the same texture. Just load a separate texture onto a separate instanced quad, using a different shader. Don't go the uber-shader way. ID3DXFONT10 is good too - it has little overhead, and it will save you a lot of headaches.

Share this post


Link to post
Share on other sites

Mipmapping will cause color bleeding with sprite sheet if there isn't a n-pixel gap between sheet elements where n is the size of the filter. Mipmapping filters use adjacent pixels to calculate the levels so it stands to reason that if you have a bunch of sprites in one large atlas, when mipmapping is applied to the atlas texture, adjacent pixels from different sprites could possibly be combined..

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!