Vertex Buffers and Texture Sorting

Started by
7 comments, last by Kylotan 24 years ago
I was just wondering how people are handling these 2 issues together. I gather that one popular way to use vertex buffers is to stream vertices into the buffer and render when it is full. I also know that sorting your polygons by texture reduces the amount of work the 3D card does and improves speed. However, my polygons are hierarchically stored as part of an object class, and it''s simplest to render an object at a time. Problem is, this can result in numerous texture changes and DrawPrimitive being called on only 6 vertices! Given that I want to leave D3D to do my transform and lighting, I was wondering about how to sort the polygons by texture before rendering them. Surely compiling a list/array/std::vector of pointers to polygons and quicksorting them each frame would be too slow? Should I keep one vertex buffer per texture and loop through all my objects copying vertex data to the correct vertex buffer, rendering when the buffer is full or at the end of the loop? Ideas, algorithms, or source code would be helpful.
Advertisement
I would build one vertex buffer, and then do one call per texture with DrawIndexedPrimitiveVB(). You''ll need one buffer with vertices and one array of triangle indices per texture.

quote:Original post by Spellbound

I would build one vertex buffer, and then do one call per texture with DrawIndexedPrimitiveVB(). You''ll need one buffer with vertices and one array of triangle indices per texture.



But how would I do that efficiently? Surely something like:

for all textures
{
for all objects
{
for all polygons
{
add to vertex buffer if the right texture
}
}
DrawIndexedPrimitiveVB
}

would be slow? (50 textures * 1000 polygons is 50000 checks even before transforming, rendering, etc.
Yes, it would be, if you''re doing it every frame. However if you do it once, preferably while saving the map there would be no slowdown.

Rendering large sets of triangles with different properties is a tricky business. There are several factors to keep in mind: Minimizing texture swaps, minimizing cache trashing due to large vertex buffers, etc. Unfortunately I don''t have enough experience to tell you the optimal way of sorting your triangles. It something that you''ll have to find by trial and error.

But if I were you I would start by sorting the triangles first by object then by texture. Sure you would get a lot more texture swaps than by sorting on texture first, but the advantage is that the sorting can be done once for each object. And then it''s a simple task of rendering the object.

If you were to completely minimize textureswaps you would have to do it at runtime, where you would keep several vertexbuffers (one for per texture) and then when rendering objects their triangles and vertices are each put in their respective vertexbuffers. Not until all objects have been processed is anything rendered to the screen. Obviously this is unfeasible, not only would it require a lot of memory it would also be slow as the card lies idle during the sorting.

Read this for some more ideas on optimizations.
Many thanks for the tips and the link, Spellbound. I must have missed that on my travels

If I were to use 1 vertexbuffer per texture, to reduce the length of time the 3d card is sitting idle I could experiment with the size of each vertexbuffer, reducing it until DrawPrimitive is being called often enough for there to be parallelism between CPU and 3D card (but not so much that DrawPrimitive overhead grows too much.)

Any other ideas, anyone? I can''t find many good examples of Direct3DIM code that deal with object hierarchies and optimal rendering order. It seems that all engines I download the source for are either very complex or simplistic like the MS samples.
I think it will be hard to find any good samples on this because it''s part of the optimization. The optimization is what shows how good a programmer is, because of that not many are willing to give out their secrets.
If you have alot of objects in you scene that can be considered of the same type, like in a space-based game you'd have more than one of each type of shit, then you could render those together, and optimizing that to group the textures would be much easier than arbitrarily sorting the entire world.

Just a thought.


Edited by - v3k on 3/18/00 11:28:56 AM
quote:Original post by Kylotan

I was just wondering how people are handling these 2 issues together. I gather that one popular way to use vertex buffers is to stream vertices into the buffer and render when it is full. I also know that sorting your polygons by texture reduces the amount of work the 3D card does and improves speed. However, my polygons are hierarchically stored as part of an object class, and it''s simplest to render an object at a time.
Ideas, algorithms, or source code would be helpful.


Hi,

I''ve just recently started checking out the message board and have only just discovered this thread and would like to offer a few pointers.

First I would strongly advocate using vertex buffers. They are the only way in which you can take advantage of TnL acceleration. I decided that each object (I prefer to think of them as resources), e.g. a hut, person, plane, tree has its own vertex buffer. Which brings me onto the second point...

As for the whole sort by texture or object debate - you should always aim to sort by texture. Changing texture is about the most expensive state change you can perform on a 3d card. To render the world I just iterate through each object in the list call its render function. I don''t bother batching objects together - there isn''t any benefit.

HTH

Chris


Chris Killpack : ckillpack@ea.com
Technology Group : Bullfrog Productions Ltd
Chris Killpack : ckillpack@eaeurope.comTechnology Group : Bullfrog Productions Ltd
Ok, thanks for the ideas. My current plan of action is this:

I add pointers to each polygon to a hashtable, with one table entry per texture (actually, it''s an STL map of vector<Polygon*>, but the principle is the same). This needs doing once at load time for static objects, and once per frame for dynamic objects (in the minority, thankfully) to a separate table which gets cleared at the start of each frame. I then loop through the tables, and for each entry, I set the relevant texture, then I add all the polygons to the vertex buffer, and render the resulting trianglelist. (I could also add the static data to a vertexbuffer to begin with and leave it there throughout, I guess.)

I am assuming here that what I lose in sorting these polygons each frame, I more than gain with the reduced number of SetTexture calls? Also, which would be the better tradeoff, keeping my immobile objects'' data static and therefore not having to sort it each frame, or to sort that each frame like the dynamic objects but adding in some sort of visibility determination algorithm such as portals?

This topic is closed to new replies.

Advertisement