8
votes

What I am trying to do is use alpha blending in XNA to make part of a drawn texture transparent. So for instance, I clear the screen to some color, lets say Blue. Then I draw a texture that is red. Finally I draw a texture that is just a radial gradient from completely transparent in the center to completely black at the edge. What I want is the Red texture drawn earlier to be transparent in the same places as the radial gradient texture. So you should be able to see the blue back ground through the red texture.

I thought that this would work.

GraphicsDevice.Clear(Color.CornflowerBlue);

spriteBatch.Begin(SpriteBlendMode.None);
spriteBatch.Draw(bg, new Vector2(0, 0), Color.White);
spriteBatch.End();

spriteBatch.Begin(SpriteBlendMode.None);

GraphicsDevice.RenderState.AlphaBlendEnable = true;
GraphicsDevice.RenderState.AlphaSourceBlend = Blend.One;
GraphicsDevice.RenderState.AlphaDestinationBlend = Blend.Zero;
GraphicsDevice.RenderState.SourceBlend = Blend.Zero;
GraphicsDevice.RenderState.DestinationBlend = Blend.One;
GraphicsDevice.RenderState.BlendFunction = BlendFunction.Add;

spriteBatch.Draw(circle, new Vector2(0, 0), Color.White);
spriteBatch.End();

GraphicsDevice.RenderState.AlphaBlendEnable = false;

But it just seems to ignore all my RenderState settings. I also tried setting the SpriteBlendMode to AlphaBlend. It blends the textures, but that is not the effect I want.

Any help would be appreciated.

1

1 Answers

6
votes

What you're trying to to is alpha channel masking.The easiest way is to bake the alpha channel using the content pipeline. But if for some reason you want to do it at runtime here's how (roughly) using a render target (A better and faster solution would be to write a shader)

First create a RenderTarget2D to store and intermediate masked texture

RenderTarget2D maskRenderTarget = GfxComponent.CreateRenderTarget(GraphicsDevice,
    1, SurfaceFormat.Single);

Set the renderTarget, and device state

GraphicsDevice.SetRenderTarget(0, maskRenderTarget);
GraphicsDevice.RenderState.AlphaBlendEnable = true;
GraphicsDevice.RenderState.DestinationBlend = Blend.Zero;
GraphicsDevice.RenderState.SourceBlend = Blend.One;

Set the channels to write to the R, G, B channels and draw the first texture using a sprite batch

GraphicsDevice.RenderState.ColorWriteChannels = ColorWriteChannels.Red  | ColorWriteChannels.Green | ColorWriteChannels.Blue;
spriteBatch.Draw(bg, new Vector2(0, 0), Color.White);

Set channels to alpha only, and draw the alpha mask

GraphicsDevice.RenderState.ColorWriteChannels = ColorWriteChannels.Alpha;
spriteBatch.Draw(circle, new Vector2(0, 0), Color.White);

you can now restore the render target to the back buffer and draw your texture using alpha blending.

maskedTexture = shadowRenderTarget.GetTexture();
...

Also don't forget to restore the state:

GraphicsDevice.RenderState.ColorWriteChannels = ColorWriteChannels.All;
...