• Advertisement

Archived

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

A Question about Vertex Buffers

This topic is 5809 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 attempting to write a sprite class using DirectX (and therefore Direct3D), but I have run into a bit of confusion over how to do the vertex buffers for the quads. I could either give each sprite its own vertex buffer that only stores 4 vertices, just enough for the quad, and change vertex buffers between every quad when drawing, which, from what I''ve heard, is not very efficient. Alternatively, I could have one big vertex buffer and give each sprite an offset into this buffer to store its four vertices. This would mean multiple drawing calls but only one setstreamsource call so set the vertex buffer, but it would mean reallocating the vertex buffer every time I add or remove a sprite and could result in lots of confusion. To do it with only one draw call would require changing the vertices in the buffer every time I moved a sprite. So which approach would be better? One big buffer or lots of small buffers? -------------------- Never eat anything bigger than your own head.

Share this post


Link to post
Share on other sites
Advertisement
One Big VB is probably the way to go, as long as you don''t need to modify the vertex data more than once a frame (or so). Just overallocate the VB so you have room at the end to add more sprites later. Also, you may be able to batch your sprites up into one DrawPrimitive...() call if you have all their vertex data in one VB.

--
Eric

Share this post


Link to post
Share on other sites
One thing I shoudl point out is that in your big vertex buffer solution, you'ld still have to cotinually change your index buffer. I'm not sure if that's a performance hit or not.

That said.. why not use only one buffer... and then change your world transform matrix? I THINK that would be faster but can't swear to it as I haven't got to the bitmap portion of the engine I'm working on.

At that point you only have one vertex buffer.. with a single set of 4 vertices.. then you just change your world transform for each bitmap you wish to render. You can even use the world matrix to scale the bitmap appropriatly. Store one world matrix for each bitmap to save calcluating it as you go.

That said, I'm not sure what kind of a performance hit there is for changing your world matrix. I'm assuming here that it's less than a stream source change or an index buffer change. (and you're right.. the big buffer that needs to be modifiable sounds ugly :o Though you could set a maximum bitmap count to avoid ever needing to recreate it. In that case you'ld have to keep track of which sets are in use and which are empty)


why not just code some quick tests in and see how they run? Pick the one with the consistantly best performance

Adendum : I know changing the world matrix has 0 impact on me when I'm drawing a hundred models and change the world matrix for each model... so unless you're drawing ALLOT of bitmaps...


Edited by - Sorrow on February 22, 2002 12:21:05 AM

Share this post


Link to post
Share on other sites
At the current stage of developement the sprites will be used almost exclusively for the menu/GUI system, so there are not likely to be a huge number at any one time.


--------------------

Never eat anything bigger than your own head.

Share this post


Link to post
Share on other sites
in that case I personally would go with changing the world matrix It''s simple and clean.

Share this post


Link to post
Share on other sites
Hmmm I think I see what you mean, and I think that would work. However, just for the hell of it, let''s assume that I don''t want to do it that way.
With one big vertex buffer, it is not necessary to change the index buffer or the vertex buffer because we can use index and vertex offsets in the Draw(Indexed)Primitive() call. So, taking this into account and remembering that we also don''t need to set any transforms except for one identity before drawing all the sprites in either case, how would you do it? Organising one big vertex buffer is very difficult and complex if you have to create and destroy lots of sprites (not worrying about a slight delay between two frames if this happens occasionally), probably requiring a reallocation every time a change is made, or at least moving vertices around in the buffer to take up slack when a sprite is removed. This would be necessary even if we overallocate.

One thing: I''m not using pretransformed vertices, I''m using an orthoganal perspective matrix instead (so that I can have a screen that goes from (0, 0) in the top left to (1.0, 1.0). If I instead use pretransformed vertices, would things become easier?


--------------------

Never eat anything bigger than your own head.

Share this post


Link to post
Share on other sites
Good point about the offset btw.

First thing.. we don't want to reallocate the buffer very often, or better yet never. Worse case we're willing to make it bigger but not to make it smaller, that way you don't have to worry about running out of sprites but your buffer will only have to be reallocated at the very beginning before you hit your cieling on bitmap allocations.


When you create the vertex buffer, you also create a list of integers. If the vertex buffer is big enough to hold 100 bitmaps, you would then add every number between 0 and 99 as an entry to the list.

Then when adding bitmaps you pop off the first entry of the list, the value that you pop is the index to be used for the new bitmap.

When removing bitmaps from the list, you push the index for that bitmap onto the end of the list (don't try and remove the vertex data, it's unnecessary.)

That's pretty much it. The only modification is that if you weren't limiting your bitmap count, the first check you'ld make when someone wants to add a bitmap is the size of the list.

if the list size > 0, there's an index, just pull it off write the vertex data and you're done.

if the list size == 0, then you're out of room for bitmaps. Pick your method and make your buffer bigger (not sure what the best way to go around that is offhand.). Don't just add room for one bitmap... add room for like, 10% of your original allocation. Return the first new index for the bitmap, add the indices for the rest of the created bitmaps to the allocation list (for future calls.)This way you'ld never have to increase the size of the buffer rapid fire for a series of consecutive bitmap additions.

That's it. All that's required to get your new index is a single list pop. All that's required to release an index is a single list push (except when you've run out of room.)

Never reduce the size of the vertex buffer, regardless of how small your bitmap count gets. There's no reason to.

Nice and Simple




Edited by - Sorrow on February 23, 2002 4:20:20 AM

Share this post


Link to post
Share on other sites
and transformed or untransformed doesn''t matter, that''s personal choice. I do however know you can, if you''re not careful, find your bottom row of pixels disappearing on you. As I''ve never had to worry about it I can''t remember the way to get around that off hand... but I''m sure you can figure it out if you poke around.

That said I doubt having your co-ordinate system in 0.0-1.0 will do you any favors in that respect. I think you''ld be better off matching your system to the screen pixel dimensions.

Share this post


Link to post
Share on other sites
I used a range from 0.0 to 1.0 to make it easier to handle different resolutions.

With the list thing: When I pop off this index, I assume that I would then proceed to lock the vertex buffer and change the four vertices that the bitmap is using?
Also: should the list hold the numbers 0 to 99 or 0 to 99 multiplied by 4 (for 4 vertices per bitmap)?


--------------------

Never eat anything bigger than your own head.

Share this post


Link to post
Share on other sites
I tried the changing the world matrix method by using the D3DXMatrixScaling() and D3DXMatrixTranslate() functions to create a matrix that would scale the vertices to the right size quad, then translate the quad to the right part of the screen, but the translation one seems to screw up the matrix. It scales fine if I don''t translate, but when I add in translation it translates OK but the scaling becomes far too high. What am I doing wrong?


--------------------

Never eat anything bigger than your own head.

Share this post


Link to post
Share on other sites
Another option has presented itself: DrawPrimitiveUP(). This function doesn''t use a vertex buffer, instead using an array stored in memory. While it would probably be slower, it may not be that much slower and it would certainly be a lot simpler to use for a sprite class.


--------------------

Never eat anything bigger than your own head.

Share this post


Link to post
Share on other sites
Hmmmm I think that DrawPrimitiveUP() function is just copying stuff into its own VB and setting the source itself. Not good.


--------------------

Never eat anything bigger than your own head.

Share this post


Link to post
Share on other sites
lol... ok... from the top

first post :

yes.. you'ld then lock the buffer.. write your vertices.. and unlock it. As to the indexing that's your call, I'd probably use the number of squares (0 to 99) and then mutliply them by 4 to get the actual buffer index. That said it's a matter of preference, either way works as long as you make sure you add the right indices to the list if and when you make the buffer bigger.

second post :

hmm.. that's wierd. I could see if your origin bitmap was in the wrong position (using the transform commands in the wrong order), but I'm not sure why it would scale wrong. What order are you issuing the commands in? What are the starting and ending vertex positions after you pass your co-ordinates through the transform matrix? Can I see a code snippet to see exactly what you're doing?

third post :

I'd try to stay away from DrawPrimitveUp myself... bad mojo =O





Edited by - Sorrow on February 23, 2002 11:32:08 PM

Share this post


Link to post
Share on other sites
I''ve fixed the problem with the scaling and translation. It turns out I wasn''t multiplying the matrices correctly. Instead of creating a scaling matrix and a translation matrix, then multiplying them together, I was creating a scaling matrix and then creating a translation one on top of that. It''s been a while since I did the 3D stuff so I''d forgotten a lot of the matrices stuff for it.

As for the VB thing: I''ve decided to go with the single 4-big VB and changing the world matrix, since that is easy to implement and works nicely. Thanks for your help.


--------------------

Never eat anything bigger than your own head.

Share this post


Link to post
Share on other sites

  • Advertisement