Home Articles Tutorials Resources About

Cullmode sorting trick for alpha blending mesh subsets


By Rim van Wersch, January 12 2006

In order to correctly render alpha blended meshes, you'll typically need to render your scene objects back-to-front, so the meshes in the background show through on any transparent ones on the foreground. For rendering complete meshes in a back-to-front order there are many resources available, but when you have a single mesh consisting of multiple subsets that use alphablending, the problem becomes more difficult to solve.

The positional data of the subsets is locked away in the mesh's vertexbuffer, so it may be quite expensive to determine the correct back-to-front order of the subsets in a mesh. And even then, subsets typically consist of independ triangles that just happen to share the same properties, which can have just about any position. So it may be entirely possible that the geometry in a mesh subset is both in the back and the front at the same time. Hence the only fail-safe way to render a mesh like this would be to render it one triangle at a time, which is of course extremely undesirable.

For solving this problem, we provide a code snippet on the cullmode sorting trick. It's sometimes considered to be more of a hack than a real technique, because it only works correctly for a limited number of meshes. But if your transparent objects are closed, convex, and viewed from the outside, culling may be used to draw the backfacing polygons prior to the frontfacing polygons. This will accomplish the same thing as sorting your objects or polygons in back-to-front order.

We used this technique in our ShipHo sample project, from which the following code is a quick excerpt. If you would like to know more about the rendering process in ShipHo, check out our Disecting ShipHo! article series.


// using our utility code to obtain a normal MDX Mesh object 
// refer to our Disecting ShipHo! series to learn how these utility classes work 
Mesh mesh = ResourceManager.DefaultManager.GetMesh( meshDescription.meshName ); 
 
// setting up the world transform 
device.Transform.World = this.WorldTransform; 
 
// This is true if this mesh has a subset that uses textures with an alpha component 
if (this.AlphaBlending) 
{ 
 ? ?// use cullmode sorting trick ? ? 
 
 ? ?// we start of with rendering the backface polygons by inverting the cullmode 
 ? ?//(the cullMode variable is supplied externally to this method and has nothing to do with the sorting trick) 
 ? ?device.RenderState.CullMode = (cullMode == Cull.CounterClockwise ? Cull.Clockwise : Cull.CounterClockwise); 
 ? ?device.RenderState.ZBufferWriteEnable = false; 
 ? ?device.RenderState.AlphaBlendEnable = true; 
 
 ? ?// render subsets as normal, effectively drawing only backfaces 
 ? ?for(int i = 0; i < meshDescription.subsets; i++) 
 ? ?{ ? ? ? ? ? ? ? ? 
 ? ? ? ?device.Material = meshDescription.meshMaterials[i]; ? ? ? ? ? ? ? ? ? ? 
 ? ? ? ?device.SetTexture( 0, ResourceManager.DefaultManager.GetTexture( meshDescription.textureNames[i] ) ); 
 
 ? ? ? ?mesh.DrawSubset(i); 
 ? ?} 
 
 ? ?// set correct cullmode and enable ZBufferWrite 
 ? ?device.RenderState.CullMode = cullMode; 
 ? ?device.RenderState.ZBufferWriteEnable = true; 
 
 ? ?for(int i = 0; i < meshDescription.subsets; i++) 
 ? ?{ ? ? ? ? ? ? ? ? 
 ? ? ? ?device.Material = meshDescription.meshMaterials[i]; 
 ? ? ? ?device.SetTexture( 0, ResourceManager.DefaultManager.GetTexture( meshDescription.textureNames[i]) ); 
 
 ? ? ? ?mesh.DrawSubset(i); 
 ? ?} ? ? ? ? ? ? 
 ? ? ? ? 
 ? ?device.RenderState.AlphaBlendEnable = false; 
} 
else 
{ 
 ? ?// just render like normal 
 
 ? ?device.RenderState.CullMode = cullMode; 
 
 ? ?for(int i = 0; i < meshDescription.subsets; i++) 
 ? ?{ ? ? ? ? ? ? ? ? 
 ? ? ? ?device.Material = meshDescription.meshMaterials[i]; 
 ? ? ? ?device.SetTexture( 0, ResourceManager.DefaultManager.GetTexture( meshDescription.textureNames[i]) ); 
 
 
 ? ? ? ?mesh.DrawSubset(i); 
 ? ?} 
}





Further reading

?
MDX info is an initiative by vector4. All content is copyright ? 2005-2006 by its respective authors | About MDX info | Terms of Use |
Coming soon!