Optimizing 2D with D3D8

Started by
8 comments, last by MatuX 22 years, 3 months ago
I just moved my iso engine from DD7 to D3D8, and added all the "common" optimizations like using VertexBuffers instead of DrawPrimitiveUP. And it''s to damn slow... I just reach 30fps on my Duron 800 256mb GF2MX, it''s even 800x600x16. It is not a code problem since I commented out the DrawPrimitive() function and it ran at +300fps. I tried commenting the SetTexture() but I only get a 20fps boost, tried disabling alpha blending and I just get a 10fps boost. I''m really really sure it''s the rendering technique I''m using. I''m using a VertexBuffer which contains 4 vertices, then I use it to render everything. What is the best way to optimize an isometric 2d game if you''re using D3D8? I''m not using the terrain blitting technique most people use of rendering a full-3d terrain, I''m blitting lots of small quads like what you do in DD7.
Advertisement
This is probably a stupid question, but here goes nothin''

Are you calling DrawPrimitive once per quad? Its just you say the VB has only 4 vertices in it - that would really be a problem if you were drawing so many quads.
Well.. I''m in problems That is exactly what I''m doing and I''m really sure that IS my problem.. But I can''t find another way of doing this..

Can anybody help me commenting out some techniques?
So.. There is no real way of developing profesional 2D games using D3D?
If you have lots of quads that use the same texture, you could put all of them into one vertex buffer. All you need to do is add the coordinates of the sprite to the coordinates of its corners and append them to the buffer. It sounds counter-intuitive because you lose the benefit of hardware vertex processing, but you cut the number of Drawprimitive calls to one per texture.

I don''t know if you can do any better than that because you have to set the texture between DrawPrimitive calls. You could get better batching by lumping many textures together into one and use the texture coordinates to pick the right one.
That is what I thought, but then, with all the terrain I will never batch more than 50 triangles, and since this is an ISO 2D the terrain will be filled with lots of different textures and not always I will have the tile I''m looking for in the texture "set" you talk about.
Plus, it has to be 256x256 to have wide support and be fast enough and I can''t put too many tiles in a 256x256 texture, so, this is not a real solution...

Conclusion, as far as now, you can''t make good 2D with D3D...
>>Conclusion, as far as now, you can''t make good 2D with D3D...
Nonsense! :-)

For starters, when you set up, don''t create a zbuffer and/or turn all z functions off. That speeds things way up.

Your sprites can be tristrip quads, or tri lists if you''re batching a lot of them together. I''ve tried batching a bunch together into one big trilist, and I found it to be slower than sending a whole bunch of individual triangle strips. meh. do whichever, but it probably won''t make much difference.

You can have hardware T&L enabled vidcards handle your 2D transformations instead of programming it all yourself using screen space vertices. Look into Orthographic projection matrices in the SDK. That''s essentially 2D transformation inside the D3D pipe. It''ll still calculate Z for the vertices, which is kinda a waste, but it''s done in hardware so the ends justify the means. Besides, with the orthographic method you also get hardware lighting on your 2D graphics. Neat-o effects are possible there.

Other than that, the usual D3D optimisation rules apply. Sort draw elements by texture, avoid too many per-frame state changes, and there''s no reason you shouldn''t be able to get 90%+ performance out of your card.

quote:Original post by MatuX
That is what I thought, but then, with all the terrain I will never batch more than 50 triangles

I''m sure that batching 50 triangles will show a significant improvement over sending them one at a time. Just send a triangle list of all the triangles using a given texture, call DrawPrimitive (or DrawPrimitiveIndexedVB or whatever it''s called these days), and repeat for every texture you''re showing.

[ MSVC Fixes | STL | SDL | Game AI | Sockets | C++ Faq Lite | Boost ]
I aggree and a method of doing this is making a wrapper for a the vertex buffer like CDrawBuffer where you could have methods like : Lock(), Unlock(), AddVertex(), Clear(), Render() and so on...

You would then have a class handling all your drawings in one snap. Another optimization could be a class CTextureBank inside
the previous class with an index relative to the vertex buffer.

With all this, you could draw primitives with grouped textures calls and batch processing accelerating the whole process.

/* Bullmax */
I forgot... you could also have a vertex buffer for each texture. All these would be linked or indexed with realloc. You could then process all the vertexbuffers and so the textures.

This topic is closed to new replies.

Advertisement