Dynamic vertex / index buffer

Started by
4 comments, last by Kopavel 14 years, 5 months ago
Consider task of rendering visible subset of game level - let's assume we have several chunks of geometry, with single material, which we want to draw by single DIP. This requires putting chunks that became visible into vertex / index buffers, and removing chunks that are no longer visible. For a large geometry, rewriting whole buffer (possibly each frame) is not an option. So how do I implement such a dynamic vertex / index buffers? Any ideas? P.S. index buffer is easier, since we can shift it's elements (so the algorithm could be - first shift remaining elements into positions of removed elements, than add new elements) Obvious solution to implementing vertex buffer would be maintaining a list of free zones (just like the system memory new / delete works), but this may result in large number of Lock() / Unlock()'s, and requires some routine coding. I believe such a problem was somehow solved in games like Warcraft 3.
Advertisement
Hey Kopavel!

Unless you are trying to render new geometry that is introduced in the vertices of a mesh during runtime, there is no need for you to bother modifying index buffer contents. In fact, what you are suggesting would make for a vicious bottle neck. It would be in your best interest to sort your polygons by attribute and create a new index buffer for each, including any values for DrawIndexedPrimitive(). This is one form of "batching", or minimizing the number of state changes and function invocations while taking advantage of any available HW acceleration.

If you haven't used ID3DXMesh before, know that it can not make a single assumption about what your geometry looks like, so it takes each primitive (In it's case, triangles in a TriList) and gives it space for an Attribute ID.

An Attribute ID is given to all triangles that are rendered alike. If you have a textured collection of N-Gons over on one end of a hallway or a vase with a sepia shader on it, each batch of primitives that make it up have a single attribute ID.



The floor, ceiling, container and walls each have their own texture applied, and can be said to have different attribute IDs. The cylinder may have attribute 1, the walls may have attribute 3... etc.

What you want to do is assign attributes to your triangles, and then sort them by said attributes. A STL Map with a DWORD key and an element std::list<polygon*> will suffice given you overload <. If you don't use C++, just use any container that automatically sorts elements by a value. After you have your polygons sorted, you will make a subset (and consequently an index buffer) for each of the polygon lists you enumerated.

When it finally comes time to render, you just choose one of your index buffers and set them for use when rendering. (Remember ID3DXMesh::DrawSubset()?)
You can render say, all trees, tigers or totem poles in your scene in fell swoop as long as you make sure all like triangles are in the index buffer.

However, you don't want to render stuff you can't see. Look up Spatial Partitioning for further optimizing your scenes. I won't go into much more detail since I don't like typing for TOO long, but I think you get the idea. [smile] If you have any trouble, let me know.

Hope this helps, and Cheers!
-Zyro
Thanks for you response, Zyrolasting.
However, I'm not sure I understand what attribute IDs have to do with rendering several chunks of mesh in a single call.
If you use index buffer for each attribute ID, that means you draw each index buffer with separate DIP.

Anyway, after googling a lot, I found this snippet -
Batching of Polygons with a Vertex Cache
It is exactly what I need, except I it's completely rewrites vertex / index buffers each frame(!!!).
Okay, after googling even more, I came along with this discussion. It adresses exactly the same problem.

So I will start writing my own implementation solving my problem, and the thread topic could be reformulated to: who else thinks he might take benefit of such functionality?
I should have clarified that what I was suggesting would help you be able to get optimal rendering with a single material, or several. I know you originally asked about one material, but let me tackle this first.

Quote:If you use index buffer for each attribute ID, that means you draw each index buffer with separate DIP.


You have a better idea? You don't have to have several IBs, but for every DIP you render under the set device states. How would you render 300 triangles with material A and 1000 with material B in one DIP call? You can't. Shaders may help in some respects, but you can only have so many shaders available at a time as well.

I'm stressing this and the attribute IDs for one good reason. Imagine you use your method and dance with your vertices and indices until you get everything visible settled: A tree and Pac-Man. They both use different textures, so you have no choice but to use 2 draw calls.

Also, you don't draw index buffers. You are only referencing the set vertex buffer. Remember this, it's important!

Quote:Anyway, after googling a lot, I found this snippet -
Batching of Polygons with a Vertex Cache
It is exactly what I need, except I it's completely rewrites vertex / index buffers each frame(!!!).


He takes care of what is essentially the last step... Putting the subsets somewhere and rendering them. He offers a way for you to replace the contents, but that's pretty much courtesy at best (Although I wouldn't do it quite like that...)

I'm trying to tell you how you can render subsets with minimal DIPs and still be able to switch states. All it would take is a loop with a few iterations to render everything in the scene, and you don't have to lock squat.

Quote:This requires putting chunks that became visible into vertex / index buffers, and removing chunks that are no longer visible. For a large geometry, rewriting whole buffer (possibly each frame) is not an option. So how do I implement such a dynamic vertex / index buffers? Any ideas


Why bother making a dynamic vertex buffer for what is meant to be unchanging geometry?

When it comes to updating scene geometry based on visibility, you only want to update the INDEX buffer! Ideally, vertices do not change in scenery.

Your idea can come in handy in something like partitioned terrains. You would dynamically build just index buffers. Even so, you would expect making several DIPS per frame anyway, since the camera may look at a hill with different patches of layered textures... And Pac-Man.

Quote:have several chunks of geometry, with single material


If you had several meshes in your scene with similar render properties, why not combine them into one mesh? That is the kind of thing you want to partition anyway.

Your main concern here should be how many triangles you pump through DIP. With the attribute ID system, you at least guarentee all different device states are organized. You are advocating that no matter the scene, you should get everything visible rendered in one DIP. It's not that simple. You have a green cube and a guy with casual clothing and a glowing arm by it. The cube is one DIP, but the guy could be several. You can't get them both with one unless you make things incredibly complex by making some huge "god" texture and shader.

I again suggest you research these topics to solidify whatever you plan to implement.


Hope this helps!
-Zyro

[Edited by - zyrolasting on November 11, 2009 2:21:53 PM]
I'm sorry for the confusion, but I was talking about rendering geometry that is generated only when it become visible.

Quote:Original post by zyrolasting
Quote:Anyway, after googling a lot, I found this snippet -
Batching of Polygons with a Vertex Cache
It is exactly what I need, except I it's completely rewrites vertex / index buffers each frame(!!!).


He takes care of what is essentially the last step... Putting the subsets somewhere and rendering them. He offers a way for you to replace the contents, but that's pretty much courtesy at best (Although I wouldn't do it quite like that...)


Well, thats exactly what I need to do. Put it all in buffer and render. And do it each frame. So how would you do that, if not that way?

Quote:Original post by zyrolasting
If you had several meshes in your scene with similar render properties, why not combine them into one mesh? That is the kind of thing you want to partition anyway.

Yep, but I need to combine them each frame.

Okay, thanks to my fellow programmer, who pointed that:
- we can afford having a lot of unused vertices in video memory. E.g. the whole Warcraft3 map could be put into memory, and then we only construct index buffer for it.

I also figured out that
- we can rewrite index buffer, since its often not much memory, and positions of index buffer elements are not important

Now I'm sure I'll be able to implement my algortihm.
Thanks.

This topic is closed to new replies.

Advertisement