I am attempting to write a DirectX 9.0 control that renders multiple 2-D shapes onto a surface and allows the user to interact with these shapes. So far I have been able to render a million triangles of different colors onto a grid and then using the mouse the user can pan and zoom around this grid. However, I believe, no wait.. I KNOW that I am doing this in an inefficient manner...
Currently, I have a vertex buffer for EACH triangle and on every render I set the stream source and draw the primitive in a giant for-loop. For an experiment, I tried making a vertex buffer containing a single triangle and in another for-loop I would change the world transform and draw the primitive. Performance was horrible.
What I really need is some way to store several unique shapes (around 100) and stamp them several 1,000 or 10,000+ times around the world. I would also like to be able to change the color of a single instance of a shape. I don't need fancy lighting/textures/or anything like that. Just a simple color.
So, what is a typical DirectX way to accomplish this?
1 Answers
There's a few techniques you could use for this; I'd start by looking into index buffers and move towards something like instancing support as your scene becomes more complex.
Generate a huge vertex and index buffer and use the index buffer to tell it which vertices from the buffer to use. You could even optimize to reduce the amount of duplicate vertices in the vertex buffer (if you have a lot of overlap), but even a naive implementation should be faster.
If you want to render a lot of transformed shapes, using a vertex shader is a great way to offload the processing challenge to a device that's designed to handle it in parallel.
Once you go with shaders instead of the fixed-function pipeline, you can pass information along with each vertex (perhaps encoding it in the Z-value or texture coordinate) telling the GPU what to do in the pixel shader when it is finally rasterized to screen (e.g. to change the colour of the primitive).
Either way, you're aiming to significantly reduce the number of times you send to and from the GPU as you pay a penalty each time you make the state "out of sync" - for instance, when you have changed the transform. Often it will be faster to send a huge lump to the card once per frame than to send tons of small lumps over the course of the frame.