XNA Alpha混合实现部分纹理透明

8
我想做的是使用XNA中的alpha混合来使绘制的纹理的某些部分透明。例如,我将屏幕清除为某种颜色,比如蓝色。然后我绘制一个红色的纹理。最后,我绘制一个径向渐变纹理,从中心完全透明到边缘完全黑色。我希望先前绘制的红色纹理在与径向渐变纹理相同的位置处是透明的。因此,您应该能够通过红色纹理看到蓝色背景。
我认为这样会有效。
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;

但是它似乎忽略了我所有的RenderState设置。我还尝试将SpriteBlendMode设置为AlphaBlend,它会混合纹理,但这不是我想要的效果。
任何帮助都将不胜感激。
1个回答

6
您想要实现的是阿尔法通道遮罩。最简单的方法是使用内容管道烘焙阿尔法通道。但如果您希望在运行时执行此操作,可以使用渲染目标(更好和更快的解决方案是编写着色器)。
首先创建一个RenderTarget2D来存储中间遮罩纹理。
RenderTarget2D maskRenderTarget = GfxComponent.CreateRenderTarget(GraphicsDevice,
    1, SurfaceFormat.Single);

设置渲染目标和设备状态

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

将通道设置为写入R、G、B通道,并使用精灵批处理绘制第一个纹理。

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

将通道设置为仅 Alpha,然后绘制 Alpha 掩模。

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

现在,您可以将渲染目标恢复到后台缓冲区,并使用Alpha混合绘制纹理。

maskedTexture = shadowRenderTarget.GetTexture();
...

同时不要忘记还原状态:

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

谢谢您的回答,这非常接近了,但是有一个问题。圆形纹理比背景纹理小,上面的代码发生的情况是只在圆形纹理存在的地方绘制背景。想法是在鼠标指针所在的位置绘制圆形纹理,用户可以透过圆形纹理看到背景。 - DangerMouse
@David,如果您需要反转阿尔法掩码,请使用白色清除阿尔法通道,并使用黑色绘制圆形。 - Pop Catalin
它起作用了,谢谢。在绘制圆之前,我不得不添加以下内容:GraphicsDevice.RenderState.DestinationBlend = Blend.Zero; GraphicsDevice.RenderState.SourceBlend = Blend.One;为了让它工作。我以为这是默认值,但直到我设置它们才起作用。感谢所有的帮助。 - DangerMouse

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接