Archived

This topic is now archived and is closed to further replies.

Andy Tuke

How many vertex Buffers?

Recommended Posts

I''m learning DirectX 8 and writing my first game, asteroids which seems like a simple start and I''ve already done it using GDI. So, I''ve got my screen up and can draw lines from a vertex buffer. So, my question is this, if I have an arbitrary list of asteroids to draw, each with an arbitrary number of vertices, should I create a vertex buffer for each asteroid and render each one in sequence or shove all my vertices into one big vertex buffer and then render that. if I do this pD3DDevice->BeginScene(); { for (each asteroid create a vertex buffer) { pD3DDevice->SetStreamSource ( 0, pVB, sizeof(CUSTOMVERTEX) ); pD3DDevice->SetVertexShader ( D3DFVF_CUSTOMVERTEX ); pD3DDevice->DrawPrimitive ( D3DPT_LINELIST, 0, 6 ); } } pD3DDevice->EndScene(); Then I''m executing the 3 DirectX functions many times, is this a problem? Any advice on the best way to implement this would be a great help Thanks Andy

Share this post


Link to post
Share on other sites
I suggest using a dynamic vertex buffer. Take a look at the SDK docs for the details. You should avoid creating a vertex buffer each frame because it will kill your performance.

Moe''s site

Share this post


Link to post
Share on other sites
At most, you should use one vertex buffer per "material" unless it needs more than 65536 vertices in which case you split it (because 16-bit indices can only reference the first 65536 vertices). By "material" I mean a set of rendering properties, such as texture, shade mode, fill mode, etc. The idea is to limit the number of DrawIndexedPrimitive calls.

What is also slow on T&L cards is changing the current vertex buffer. T&L cards transform the vertices so they should (and will) be placed in AGP memory. The transition from RAM to AGP, or vice versa, is very slow, so that's why you don't want to change the active vertex buffer any more than necessary.

For more advanced optimization, you can use a single vertex buffer for multiple materials. You can, say, select the spaceship texture, and put its geometry in the beginning of the vertex and index buffers, and call DrawPrimitive for the part of the buffers that has the ship's geometry. Then you select the asteroid texture and render the remaining portion of the vertex and index buffer.

Pseudocode:

SetStreamSource( 0, VBuffer, sizeof OneVertex );
SetIndices( IBuffer, 0 );
SetTexture( 0, Spaceship );
DrawIndexedPrimitive( D3DPT_TRIANGLELIST,
0, // first vertex
NumShipVertices, // num vertices
0, // first index
NumShipIndices / 3 ); // num triangles

SetTexture( 0, Asteroid );
DrawIndexedPrimitive( D3DPT_TRIANGLELIST,
NumShipVertices, // first vertex
NumAsteroidVertices, // num vertices
NumShipIndices, // first index
NumAsteroidIndices / 3 ); // num triangles


~CGameProgrammer( );



[edited by - CGameProgrammer on April 30, 2002 4:50:27 PM]

Share this post


Link to post
Share on other sites
Are you both saying that I should maintain one large vertex buffer and keep that up to date with all my vertices?

I''m thinking of maybe having just the vertices for untransformed asteroids, ie one big, one medium and one small then placing and rotating each one onto the screen. Guess I have some more reading to do to work that one out.

Thanks for the help

Andy

Share this post


Link to post
Share on other sites
Second thought.....

If I have an asteroid class which has a vertex buffer as a member variable I can simply tell each asteroid to render itself which obviously give nice encapsulation. I think I am being told that I want my vertices stored in the graphics card memory but with 8 or so vertices per asteroid and say 50 asteroids max then I''m not using too many in total, will they all get stored on the card or only the current one?

A

Share this post


Link to post
Share on other sites
for starters, since this is your first game in direct3d (right?) I''d go with that last method you just described.
It will be a bit slower, cos each time you draw an asteroid, you''ll need to switch vertex buffers, but I imagine there won''t be too many of them to draw so speed probably (in such a small game) won''t be an issue.

I did it that exact same way in my first direct3d game, and while it wasn''t the fastest way, it was the easiest to get my head around first off. Once you get it working that way , consider having a single dynamic vertex buffer, which is a static member variable in the class, so every asteroid can chuck its vertices in it each frame, and then you just render that one vertex buffer, which will be faster, but harder to understand (at first anyway)..

good luck
Toby

Gobsmacked - by Toby Murray

Share this post


Link to post
Share on other sites
G''day!

If I read your code properly you were actually creating a VB in a loop every frame? Yeah, that''s not good.

You can do a lot of cool things with dynamic VBs and cool batching, but in this case I think it''d be a waste.

In my little 2D game I have about 100 objects on screen, and they all draw themselves and I still get about 600FPS on a Matrox G400. I haven''t tested it on my Radeon yet, but I imagine it''d be an obscene # of FPS.

It''s not the fastest way, but why put effort into optimizing this to get to 700FPS?? Who cares?

Create your VBs as MANAGED and let D3D worry about where they go. Spend the optimization effort where it''s worth it, and for the rest, go with nice simple encapsulation. If you find it''s necessary you can re-write the render bit in you asteroid class to do batching and not have to change the rest of your program.


Stay Casual,

Ken
Drunken Hyena

Share this post


Link to post
Share on other sites
CGameProgrammer: The 65536 vertex limit is only for index buffers (unless your video card supports 32bit indices, which some cards do. In which case, the limit isn''t valid at all). To my knowledge, vertex buffer size is only limited by how much memory you have. If you make a VB larger than your video ram it''ll probably just store it in main memory. If you make a VB larger than main memory (I have no idea why you''d want to, you''d never even want to make one larger than video RAM) I''m not sure what it''d do. Maybe it''d store it in swap memory.

To access a VB larger than the max number of indices allowed, you use the setIndices() function to tell the drawIndexedPrimitive() call to start reading the vertices from a different place in the VB. For instance, if you use setindices() to tell it to start rendering from vertex_buffer[65000] then vertex_buffer[65000] becomes index value 0 in the index buffer and the drawIndexedPrimitive() goes from there. Also, there is another offset value passed into drawIndexedPrimitive() that allows you to start even further into the VB than the value you passed to setIndices().

-Daedalus

Share this post


Link to post
Share on other sites
quote:
Original post by Daedalus
CGameProgrammer: The 65536 vertex limit is only for index buffers (unless your video card supports 32bit indices, which some cards do. In which case, the limit isn''t valid at all). To my knowledge, vertex buffer size is only limited by how much memory you have.

As far as I know, thats not entirely true. There is a vertex cache limit of something like 64k, or at least I remember hearing this from either somewhere on the ''boards or in an Nvidia paper. It probably wouldn''t be advisable to exceed 65536 vertices.



Moe''s site

Share this post


Link to post
Share on other sites
quote:
There is a vertex cache limit of something like 64k

I''ve heard about that before... and a simple landscape engine I made years back (well, D3D7 ) would fail if I tried to render more than 64k vertices (or so), so I had to split the buffers apart...

Jack;

Share this post


Link to post
Share on other sites
There''s an effective vertex buffer cap of 65536 if you''re using 16-bit indices, I believe. I say "I believe" because I''m not sure if each 16-bit index is added with BaseMinIndex, or if BaseMinIndex is only added towards the end, after converting the index to a long.

Also there doesn''t seem to be any 65536-index cap, as I have an index buffer with 196000 indices (and a GeForce2). However, with OpenGL, I can''t have index arrays of more than 65536 indices.

~CGameProgrammer( );

Share this post


Link to post
Share on other sites