Archived

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

Using Dynamic VBs effectively?

This topic is 5337 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''ve been told that one of the more efficient ways to render asside from simply batching poly''s and limiting settexture/setrenderstates is to use a dynamic vertex buffer and recalculating it each change/frame. How would one use this instead of setting the world matrix and using a static buffer? For example right now my code does the following to render a given set of triangles based on there world position. The triangles are described in model space around the origin, so I change world matrix to move/rotate them into place. D3DDevice->SetTransform(D3DTS_WORLD, &matWorld); D3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST, FirstTriangle, NumOfTriangles); How would this be done with a Dynamic VB? Here''swhat I''ve gathered so far... I''d have all the vertices/triangles held somewhere. Then I''d BYTE *Bytes; pVB->Lock(0,0,&Bytes,D3DLOCK_DISCARD); // Lock/flush VB // WHAT do I do here? The Vertex Data is in model space, how should I go about transforming it to world space? memcpy(Bytes,VertexData,VertexDataSize); pVB->Unlock(); // then draw as poly''s as possible at once.. Anyway I hope you can see the question I have. I''m pretty much a beginner with D3D. And I used D3DX for matrices. I''m sure this probably has something to do with using them on the vertex data before copying it to dynamic VB. Als any info on using Index buffers with a dynamic VB would be apprieciated Thanks!

Share this post


Link to post
Share on other sites
You don't transform vertices before placing them in dynamic VBs. You use a dynamic VB exactly as you would a static VB -- the only difference is that locking/creating static VBs is much slower than dynamic ones, but static VBs are transformed/rendered faster than dynamic VBs, as long as they aren't huge.

EDIT: Also there's the DISCARD/NOOVERWRITE flags. It's easiest to just use DISCARD -- an advanced optimization uses NOOVERWRITE but you don't need to worry about it for a while.

~CGameProgrammer( );



[edited by - CGameProgrammer on May 6, 2003 11:54:32 PM]

Share this post


Link to post
Share on other sites
Ah ok, Well I was adviced to avoid using setTransform calls as much as possible. How can this be done? Each object requires atleast one SetTrasform call as far as I see it.

Also If I don't see how I'm going to be changing the VB much (atleast not yet) So how are Dynamics going to help me? Copying the vertex to a dynamic every frame or change basically gives me the ability to batch polys more effectively... Thats the only thing I really see. Is that basically the idea?

Which do 3D Engines genereally use for what? do they mix both?

Thanks again

[edited by - Illumini on May 7, 2003 1:08:05 AM]

Share this post


Link to post
Share on other sites
Well I thoguht of a reason for using dynamics, mainly because you want to pack as many polys as posible int oa vb and therefore doing so with a static would mean nothing in the world could change easily. Where as a dynamic allows faster modification of vertex data (for animation/character movement etc). anyway here is some an example where I have a terrain object and a player object. Player uses texture A and B, terrain uses C and D with mutlitexturing... To make it intresting say there are a few objects one terrain that use texture A.

// assume this is there is only one dynamic vb and its set
lock vb
..copy player to vb
..copy object to vb
..copy terrain to vb
unlock vb
setstate default
..settexture A
....settransform for player
....draw player A polys
....settransform for object1
....draw object1 A polys
....settransform for object2
....draw object2 A polys
....settransform for object3
....draw object3 A polys
..settexture B
....draw player B polys
setstate for multitexturing
..set texture A & B
....draw terrain A & B polys

doing this every frame, the vb part could be consolidat to only updating when something in scene changes, but thats the basic idea. Also the series of object# with settransform/draw, is there a better way to do this. Set transform is slow from what i''ve heard but calling it once per object seems to be neccesary.

now if i did it with a static vb. i couldn''t reaonably update it so frequently? I''d want to just stuff the vb at begining, but aniation of players verts would require a seperate dynamic vb? in which case I''d have a set vb call in there some where as well.

Share this post


Link to post
Share on other sites
For anything that is animated you always use dynamic buffers. And yes, those SetTransforms are necessary. What is slow is basically changing anything with the card, such as render properties, transformation matrices, currently used buffers, etc. As far as I know, SetTransform isn''t unusually slow, but make sure you don''t call it redundantly. So if your world-matrix doesn''t change then don''t keep calling SetTransform for the world matrix, for example. Similarly you never want to set a render property, like the texture being used or the fillmode or whatever, if it''s already been set as that value -- you''re just wasting valuable time otherwise.

~CGameProgrammer( );

Share this post


Link to post
Share on other sites
So should my engine keep track of what its currently set the render state to? or is calling GetRenderState much faster than SetRenderState and thus should be used before calling a Set to assure its not redundant?

Share this post


Link to post
Share on other sites
Yes, you should try to keep track of the render states, or at least the slowest and most often used ones.

Also something to bear in mind is that if you create a pure device then the Get* calls dont actually work.

SetTransform isnt really that slow, so dont spend too much time trying to reduce the number of calls to it. Once per object is fine, and expected.

Having said that, heres some ways you can reduce the number of SetTransform calls...

An example of how you can use a dynamic VB to reduce the number of SetTransform calls is for particle systems. If you had 2000 particles and render each one seperately, with a SetTransform call before it, then that would be very slow. Instead what you do is use a dynamic VB and create the geometry directly in world-space.

If you have a bunch of meshes in your scene that you know are static you can pre-process the scene to transform the geometry into world-space (and into the same VB). This is something I''ve done with exported MAX scenes before with great results. Its done as a pre-process though, not at runtime. Essentially you''re merging lots of small meshes into a single large mesh.

Another way of reducing the number of SetTransform calls for lots of very small models is to use single-weight skinning. This is where you put all the models into a single VB, and you use the concept of skinning to select the world matrix that each ones uses. Actually, this still requires the same number of SetTransform calls, but it means you can render all the models in one go, rather than the interleaving them with SetTransform calls.

Share this post


Link to post
Share on other sites
Yeah, as treething said, Get functions are the slowest and they don''t work with puredevices anyway. I keep track of all renderstates and use an if statement for each at run-time to make sure I''m not setting anything that''s already been set.

~CGameProgrammer( );

Share this post


Link to post
Share on other sites
I'm not totally sure what you guys talk about but, how would it be if you only had one vertexbuffer and each frame copy vertexes from different objects to that vertexbuffer and had an array wich kept track of which offset each object start and end on. And when getting to an offset where a new object starts call for that objects render states?

It would be good if you had some sorting algorithm just before copying the data to the new vertexbuffer. Something that will sort depending on what renderstates an object has. Like object one has:

STATE1 <- object1
STATE1 <- object2
STATE1, STATE2 <- object3

Though this would mean that every object would need to have the same Vertex size.

Maybe have 2 or three VertexBuffers in case you get over 10000 vertexes at once?

Or maybe I'm just out on a ride up in the sky?

I dunno, I haven't actually gotten this far in my D3D tutorials... but to me, it sounds very good

[edited by - bilsa on May 7, 2003 4:18:23 PM]

Share this post


Link to post
Share on other sites
Thats basically my idea for dynamic objects atleast. Static are going to work similar except tehy won't have to be copied to the vb each frame. I actaully have two classes, one is a Texture class and the other is a State class, then you make instance of one of those for each possible state set and texture set (multitexturing etc).

I'm trying to decide whether I could integrate them into one set of state and texture. There would be more of them of course, and some would be a waste of space,but how big could a StateSet/Texture set class really gonna be lol. A few texture pointers,a vector of two DWORDS for states and there values. Not sure how much te overhead weight is for an STL vector but I think its rather small.

As long as I always check te State/Textures before setting them I should probably be ok.

Just checked it out, an empty vector is 16 bytes.

So my state class would be 16+4+4= 24bytes with a state vector and 2 texture pointers.

So in a simple terrain example 100x100 quads using multi texturing..

If i had seperate state and texture classes

We'd need 16 byte state for multitexturing
and assuming terrain used 10 textures, 80 bytes of texture classes...


if i consolidate the two.. thats 24*10= 240 bytes for the terrain state/texture classes. Not a big deal really, even tho its three times as much I was just kinda worried about adding to much overhead around something simple.

[edited by - Illumini on May 7, 2003 6:39:26 PM]

Share this post


Link to post
Share on other sites