Sign in to follow this  
SlimTimmy

optimize 2D rendering

Recommended Posts

Hello, I want to create a small 2D engine, which should be based on Direct3D. Sprites should be rendered as textured squads. Now I am thinking about a way to optimize the rendering pipeline (for example, by sorting the sprites by texture) I had 4 methods in mind and would like to hear your opinions about them. 1) Very simple: Batch all sprites in a dynamic vertex buffer. (just one lock+unlock) Then render each sprite separately (many DrawPrimitive calls, a lot of overhead) 2) Similar to 1), but: Instead of drawing each sprite separately, try to group sprites, which use the same texture and which normally would be rendered one after another. Example: The user passes the following sprites to the engine: Sprite0(Tex0), Sprite1(Tex1), Sprite2(Tex1), Sprite3(Tex0), Sprite4(Tex1) Sprite1 and Sprite2 would be rendered with one call. Sprite4 cannot be included, as Sprite3 may lie under Sprite4. 3) Use a layering system. The user creates layers (each layer has its own z-Value) and puts sprites on them. Each layer is rendered separately with textures being sorted. (It is assumed that on one layer there are no overlying sprites) 4) Try to reduce all sprites to one layer: If a sprites lies above another, the sprite which lies on top will be subtracted from the lower sprite (using boolean operations). This will also avoid overdraw. Then you are able to render all sprites (sorted by texture) without paying attention to their z-Value. (Problem here: I have not thought about textures with alpha channels. Rendering transparent sprites would increase the complexity of this algorithm) I would be glad if you could give me some advice. Maybe some solutions (especially the last one) would even negatively influence the performance. I have not thought about using the z-Buffer either, as I consider it to be not accurate enough. By the way: Does anybody know which method is used by the implementation of the ID3DXSprite interface?

Share this post


Link to post
Share on other sites
The ID3DXSprite interface does all this for you, they've even updated it for the August SDK for better batch sorting. Check it out before putting in all the work of making your own. You might get a few good ideas you hadn't thought of, so even if it doesn't meet your needs, you're a little better off if you end up writing your own.

Share this post


Link to post
Share on other sites
Quote:

I have not thought about using the z-Buffer either, as I consider it to be not accurate enough.

It is accurate and fast, and I recommend using it. First render all opaque sprites from front to back, and then transparent sprites from back to front. This way you don't have to care much about layers.

About batching: In my 2D engine I use DrawUserPrimitives (DrawPrimitiveUP() in unmanaged Direct3D) to render as many sprites at a time as possible. Although I haven't done any serious performance tests yet, as the engine is in very early stage, it seems fast enough. Your method 2) seems quite similar.

EDIT: And yeah, I also recommend using ID3DXSprite if you don't need anything more advanced than textured quads.

Share this post


Link to post
Share on other sites
Then I would use a 16 bit depth buffer (D3DFMT_D16). Does anybody know how the bits are arranged? (How many bits are used for the mantissa/exponent)

I am using pretransformed vertices and currently set the z-coordinate to a value between 0 and 1. Do you proceed the same way?
How great is your "step" value? (I mean the distance between two consecutive sprites)
I found out that a step size of 1/65536 still gives correct results.

Share this post


Link to post
Share on other sites
Quote:
Original post by SlimTimmy
Then I would use a 16 bit depth buffer (D3DFMT_D16). Does anybody know how the bits are arranged? (How many bits are used for the mantissa/exponent)

Well, I dont know how the bits are arranged, but you don't have to care about that, leave that to hardware. [smile]
Btw, 16-bit depth buffer may cause some visual errors because of its limited accuracy. I use 24-bit depth buffer with 8 bit stencil (D3DFMT_D24S8), but if 16 bits is enough for you, you don't have to change it.

Quote:
I am using pretransformed vertices and currently set the z-coordinate to a value between 0 and 1. Do you proceed the same way?

I use ortho projection matrix and set z-values between -1 and 1000. Each sprite's depth can be set to any arbitrary value between these. There can be multiple sprites on same depth, but then their order is determined by draw order.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this