Jump to content
  • Advertisement
Sign in to follow this  
brekehan

sort by material

This topic is 3450 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

So for efficiency, it was said that opaque objects should be sorted by material as to minimize shader variable changes. As I code such a thing up, I really have to wonder A) How exactly am I going to sort by material? There are differant sets of attributes of each effect Those attributes may vary or not between differant sets of polygons It's not like I can give them an ID, as material attributes change every frame. So, I am going to have to write some material compare function I guess? B) How in the world is this going to be more efficient? To sort by material, I'd have to go through every single rendered opaque object one by one, get its material, then compare every attribute of the material with the next object's. It looks like O(N!) comparisons per frame! Is that really going to be faster than just changing a few shader variables for each object? With alot of objects, I could see that taking over a minute just to do comparisons rather than 1/3rd a second for everything.

Share this post


Link to post
Share on other sites
Advertisement
The idea is minimize the number of times the STATE of the render is changed.
Sort by textures.
Sort by shader programs.
Sort by blending modes.
The specific variables needed by any one shader program will always incure the upload cost, but that should end up small compared to swaping out the shader program.

Share this post


Link to post
Share on other sites
This is the solution I use at present. Admittedly it's far from perfect, but in tests I've found that it can still improve performance significantly.

1) Assign each material a unique ID
2) Store a pointer to each object you want to render, along with that object's material ID
3) Use a radix sort algorithm to sort the material IDs

Here's a bit of pseudo code:


std::vector<Object *> objects;

std::vector<int> materialIDs;

void RenderObject(Object *pObject)
{
objects.push_back(pObject);

materialIDs.push_back(pObject->GetMaterialID());
}

void Process()
{
std::vector<int> sortResults;

RadixSort(materialIDs, sortResults);

int numberOfObjects = (int)objects.size();

for(int i = 0; i < numberOfObjects; ++ i)
{
objects[sortResults]->Render();
}

objects.clear();

materialIDs.clear();
}




Obviously I wouldn't suggest you implement your system exactly like this, the pseudo code's just for simple illustration purposes really.

The only real drawback with the system (so far as I know) is that if a material changes, it retains it's original ID, and this means that animated materials aren't always sorted very efficiently. However there are usually enough static materials in a scene to mean that the sort is still worthwhile, and radix sorts are generally very fast anyway, so it's not likely to make your game run any slower.

[Edited by - pauls_1979 on January 7, 2009 6:55:14 AM]

Share this post


Link to post
Share on other sites
I think sorting is evil. Unless you NEED to sort things (i.e. alpha blended objects), 90% of the time you sort things it's a just an avoidable bottleneck.

The huge amount of work needed to optimize something can result in nothing but a small improvement. In that case it's better to rethink about your goals from a different POV.

I suggest OP to think about the level of flexibility he needs.

Do you really need perfect sorting?
Do you really need every material to be animated?
Do you really need every possible shader permutation?

Many games shipped support "impressive features" like:
- baked lighting
- very limited amount of dynamic lights
- static world geometry

And they're absolutely amazing!

The point is it is likely that the vast majority of your material sorting will end up affecting meshes belonging to "world" (they are static). Being static, there's no reason to mess up with them every frame, as you could just precalculate an ordered list. As suggested, order it by textures and by shaders, not by shader variables.

If your level has an huge building and 10 characters, there's no point in sorting characters toghether with world geometry, as it is likely your main character isn't going to share the same material you use for a wall/floor/window/door/table.

I would go for separate lists: one order independent (10 different characters will probably never share the same texture set, so there's no reason to sort them. Furthermore this list is going to be small, so it's a waste of resources to sort it) and another one semi-orderer (static/world). When a part of the world appears or is removed, sorting process should be easy as you only need to find the proper place for the new item/tag the removed one as not visible.

If you have materials whose texture set/shaders vary over time, then you can use another list and sort it.. or allow the state to change, as it is likely that the number of materials animating will not be huge.

In general I prefer to decide some limitations which help writing smaller/faster/better code than to allow my code to do everything and waste days trying to optimize something I'll never use.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!