DepthStencilView & Transparency Woes

August 27, 2011

The SlimDX examples have no reference to the depth buffer. XNA creates one by default with SlimDX you have to create one yourself.

Texture2DDescription depthdesc = new Texture2DDescription();
            depthdesc.BindFlags = BindFlags.DepthStencil;
            depthdesc.Format = Format.D32_Float_S8X24_UInt;
            depthdesc.Width = Window.Width;
            depthdesc.Height = Window.Height;
            depthdesc.MipLevels = 1;
            depthdesc.SampleDescription = new SampleDescription(1, 0);
            depthdesc.Usage = ResourceUsage.Default;
            depthdesc.OptionFlags = ResourceOptionFlags.None;
            depthdesc.CpuAccessFlags = CpuAccessFlags.None;
            depthdesc.ArraySize = 1;
Texture2D depthTexture = new Texture2D(GraphicsDevice, depthdesc);
depthStencilView = new DepthStencilView(GraphicsDevice, depthTexture);
GraphicsDevice.ImmediateContext.OutputMerger.SetTargets(depthStencilView, renderTargetView);

And for some reason the DepthStencilState is disabled by default, so you have to create a new DepthStencilState and apply it in your draw code.

DepthStencilStateDescription dssd = new DepthStencilStateDescription
     IsDepthEnabled = true,
     IsStencilEnabled = false,
     DepthWriteMask = DepthWriteMask.All,
     DepthComparison = Comparison.Less,
depthStencilStateNormal = DepthStencilState.FromDescription(GraphicsDevice, dssd);

GraphicsDevice.ImmediateContext.OutputMerger.DepthStencilState = Game.depthStencilStateNormal;

This works almost as expected. That nasty sharedsurface workaround for text is troublesome. It is technically a texture drawn over the entire screen, most of the texture is transparent (Alpha=0) with the rest as test with an Alpha=1. The GPU doens’t care what the Alpha is, it treats the transparent pixels in my text overlay as “in front of” everything. So my nicely tessellated sphere dissapears. I hacked around a bit trying to turn off the depth functions for the text overlay, no luck so far. I did however find an interesting workaround. If you modify the text overlay pixel shader you can use the discard command to exit before writing anything, thus leaving the depthbuffer unchanged, also leaving my new sphere visible.

float4 PS( PS_IN input ) : SV_Target
	float4 color =  g_textOverlay.Sample(g_samLinear, input.Tex);
	if (color.a <=0)
	return color;

This seems to work for the moment. I suspect I will need to revisit transparency in the future. There are several articles on the Internet that discuss sorting transparent objects, and drawing them last. Seems like a lot of work, and since I have only 1 transparent object at the moment I’m going to defer the problem until later.

Leave a Reply

You must be logged in to post a comment.