Device AlphaBlend state in XNA 4.0
I'm having a problem getting the BlendState on the graphics device to work properly and display the alpha blending correctly.
In some cases you can see the leaves through other leaves, in other cases you cannot. And the trunk is also always obscured.
I've tried so many different combinations of setting up the BlendState. At the moment it looks like this:
GraphicsDevice.DepthStencilState = DepthStencilState.Default;
GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise;
//GraphicsDevice.BlendState = BlendState.AlphaBlend;
GraphicsDevice.BlendState = new BlendState()
{
AlphaBlendFunction = BlendFunction.Add,
AlphaDestinationBlend = Blend.InverseSourceAlpha,
AlphaSourceBlend = Blend.One,
BlendFactor = new Color(1.0F, 1.0F, 1.0F, 1.0F),
ColorBlendFunction = BlendFunction.Add,
ColorDestina开发者_如何学JAVAtionBlend = Blend.InverseSourceAlpha,
ColorSourceBlend = Blend.One,
ColorWriteChannels = ColorWriteChannels.All,
ColorWriteChannels1 = ColorWriteChannels.All,
ColorWriteChannels2 = ColorWriteChannels.All,
ColorWriteChannels3 = ColorWriteChannels.All,
MultiSampleMask = -1
};
The shader code are as follows:
float alpha = 1.0F; if (HasAlphaTexture) alpha = tex2D(AlphaSampler, IN.UV).xyz;
//... //determine color values etc.. ///...
return float4(result.xyz,alpha);
The maps I'm using for this looks like the following:
First of all you want to either sort your geometry or use alpha-testing, because you cannot combine Z-buffer (aka: depth-buffer) based rendering with transparency. There is no way to "blend" a Z-buffer value - so it always uses the topmost value, blocking off the things behind, even when the colour you are rendering is transparent.
Take a look this article for an explanation (and this one for a word on quality). This will solve your problem of geometry sometimes not showing up behind some transparent geometry.
The problem with your blend state is that you're using premultiplied blending with data that has not been premultiplied.
See this article for an explanation of premultiplied alpha. It was made the default in XNA 4.0.
When you premultiply, you scale your colour values (RGB) by your alpha value (ie: you multiply them) before you blend them (ie: pre).
So there are two possible solutions: you could use BlendState.NonPremultiplied
. But premultiplying has benefits (as explained in that aritcle), so the better solution is to perform the multiplication in your shader like so:
return float4(result.xyz * alpha, alpha);
Of course, it is preferable to simply use a single texture with an alpha channel, if that is at all possible. If you can't combine the alpha channel using your art tools, you could use the XNA Content Pipeline to combine the two textures and perform premultiplication during your build. The default Content Pipeline texture importer does premultiplication by default.
精彩评论