• Advertisement
Sign in to follow this  

State Sorting for Alpha Test/Blend

This topic is 3824 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 have question about state sorting/blend optimization. I have a renderer that sorts object by material, metamaterial, depth , etc... At initialization all diffuse color textures are scanned and labeled one of these three "blend state" categories: 1. Opaque: The entire texture's alpha channel is 1.0 or there is no alpha channel. 2. Transparent: The texture's alpha channel consists of only 1.0 or 0.0, essentially a mask. 3. Translucent: The texture's alpha channel has values ranging [0.0, 1.0] In general, but also depending on the material, "blend states" 1 and 2 are sorted by state priority first (metamaterial, material) then by depth from the camera, in front to back order for early-z outing. Logic behind this is that in practice changing shaders every object is way more costly than non-optimal early-z. State 3 is sorted purely on depth, back to front, to preserve correct alpha blending (shader switch overhead nightmare but oh well). Now, my question is, should states 1 and 2 be differentiated at all? Case 1: Opaque and transparent objects sorted and rendered seperately AlphaTest = false AlphaBlend = false Render opaque objects AlphaTest = true AlphaBlend = false Render transparent objects AlphaTest = false AlphaBlend = true Render translucent objects The benefits of this method are that all objects are drawn with only the neccessary overhead of alpha test/blending per pixel. The draw back is that there will be more *redundant* shader switches because many opaque/transparent objects share the same shaders. Case 2: Opaque and transparent objects sorted and rendered together AlphaTest = true AlphaBlend = false Render opaque and transparent objects AlphaTest = false AlphaBlend = true Render translucent objects This method offers better shader batching but it means that the opaque objects are being alpha tested, and the majority of objects will probably be opaque. Case 3: Alpha test state is set for each opaque/transparent object AlphaBlend = false Render opaque and transparent objects : AlphaTest = (object.blend == Transparent) AlphaTest = false AlphaBlend = true Render translucent objects This offers optimal alpha blend/testing and sorting, but means a possibly AlphaTest state change for every opaque/transparent object, which I'm not sure is fast or not. So, which case would generally perform better and why? Or should I leave it open to testing and even select a method dynamically?

Share this post


Link to post
Share on other sites
Advertisement
The only way to be certain is to try it out and profile it, the answer will depend on the hardware and scene, but I can take a guess for you.

If you have a large transparent object in the foreground then rendering that first will mean that the z-buffer will cull lots of things it wouldn't have if you rendered all the opaque objects first. That will be a big speed up, especially when they have complex pixel shaders.

On the other hand turning alpha testing on will probably turn off the hardware's hierarchical Z-Buffer which may slow things down a bit, so I'd consider a 4th option - turn the alpha test on when you draw the first transparent object. This is obviously better than case 2 when there are no visible transparent objects.

Share this post


Link to post
Share on other sites
Yes, its worth separating as you can halve/quarter your fill rate simply by enabling alpha test on some h/w parts. What you have now is a good solution, and will scale well to the 360 should you ever tackle it.

Share this post


Link to post
Share on other sites
My testing environment is quite inaccurate currently (very few objects < 10, profiling done without d3d query for actual costs, etc...). However, it does indicate that shader switches or their incurred flushing of the driver pipeline take up 20% of my CPU cycles, and when there are fewer shader switches, that percent cost does not change, but the overall fps goes up. I will of course have to improve the tests to get accurate profiling, and the scene does not currently represent what will most likely be used, so I think you are probably right, I will leave them seperate, 100% batching of the alpha test/blend groups, and see what happens.

As a side note, how much does SetRenderState(ALPHATEST/BLEND, TRUE/FALSE) actually cost? Is it something you want to do only a few times a frame? Or is something that could be set like a texture, per object/material?

Share this post


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

  • Advertisement