单眼的AlphaMask无法正常工作

时间:2014-02-05 03:34:43

标签: c# .net xna monogame

我试图为战争迷雾建立一个rendertarget alpha蒙版示例..我告诉它我要用纯白色清除rendertarget(Alpha 255)

然后我用透明圆圈绘制我的图像到alpha通道上,从那里我希望在rendertarget中有一个图像,里面有洞。然而事实并非如此..我非常熟悉alpha遮罩,并且在将单个图像绘制到alpha蒙版时已经成功完成了,但是当我们在这里绘制一堆时,它完全无法给我正确的alpha值。

if (mFogOfWarRT == null)
{
    mFogOfWarRT = new RenderTarget2D(pGraphics.GraphicsDevice, MapSize, MapSize);
    pGraphics.GraphicsDevice.SetRenderTarget(mFogOfWarRT);
    //pGraphicsDevice.Clear(Color.Black);
}
else
{
    pGraphics.GraphicsDevice.SetRenderTarget(mFogOfWarRT);
}

pGraphicsDevice.Clear(Color.White);
pSpriteBatch.Begin();
BlendState lKeep = new BlendState();
lKeep.AlphaSourceBlend = Blend.One;
lKeep.AlphaDestinationBlend = Blend.Zero;
lKeep.ColorSourceBlend = Blend.Zero;
lKeep.ColorDestinationBlend = Blend.One;
lKeep.ColorBlendFunction = BlendFunction.Subtract;
lKeep.AlphaBlendFunction = BlendFunction.Add;
pGraphicsDevice.BlendState = lKeep;
pGraphicsDevice.BlendState.ColorWriteChannels = ColorWriteChannels.Alpha;

foreach (ClearArea lArea in mDrawQueue)
{
    pSpriteBatch.Draw(mAlphaMask, new Rectangle((int)lArea.X, lArea.Y, lArea.Diameter, lArea.Diameter), Color.White);
}
//pSpriteBatch.Draw(mDot, new Rectangle(0, 0, 100, 100), Color.White);
pSpriteBatch.End();

pGraphicsDevice.SetRenderTarget(null);

这是我的alpha蒙版的绘图代码..当绘制到屏幕时,我们得到一个白色正方形,没有别的。

下面我将我的“地图”绘制到RGB,然后设置A,并绘制我的alphamask纹理,它失败了

pGraphicsDevice.SetRenderTarget(null);

// Draw minimap texture
pGraphicsDevice.Clear(Color.CornflowerBlue);
pGraphicsDevice.BlendState = lKeep;
pGraphicsDevice.BlendState.ColorWriteChannels = ColorWriteChannels.Red | ColorWriteChannels.Blue | ColorWriteChannels.Green;

pSpriteBatch.Begin();
pSpriteBatch.Draw(mDot, new Rectangle(0, 0, 400, 400), Color.Blue);
pGraphicsDevice.BlendState.ColorWriteChannels = ColorWriteChannels.Alpha;
pSpriteBatch.Draw(mFogOfWarRT, Vector2.Zero, Color.White);

pSpriteBatch.End();

对此的任何帮助都会非常感激..

完整代码的粘贴箱

http://pastebin.com/KsEVaW0d

如果需要,可以获得结果的屏幕截图。

1 个答案:

答案 0 :(得分:1)

决定在进行研究后,alpha掩蔽不是最好的方法,我找到了Stencils。

下面的代码通过写入模板缓冲区来解决问题。

graphics.PreferredDepthStencilFormat = DepthFormat.Depth24Stencil8;
graphics.ApplyChanges();

AlphaTestEffect alphaTestEffect = new AlphaTestEffect(pGraphicsDevice);
alphaTestEffect.VertexColorEnabled = true;
alphaTestEffect.DiffuseColor = Color.White.ToVector3();
alphaTestEffect.AlphaFunction = CompareFunction.Equal;
alphaTestEffect.ReferenceAlpha = 0;
alphaTestEffect.World = Matrix.Identity;
alphaTestEffect.View = Matrix.Identity;
Matrix projection = Matrix.CreateOrthographicOffCenter(0, 400,400, 0, 0, 1);
alphaTestEffect.Projection = projection;
        // Create fog of war mask
        if (mFogOfWarRT == null)
        {
            mFogOfWarRT = new RenderTarget2D(pGraphics.GraphicsDevice, MapSize, MapSize, false, SurfaceFormat.Color, DepthFormat.Depth24Stencil8);
            pGraphics.GraphicsDevice.SetRenderTarget(mFogOfWarRT);

        }
        else
        {
            pGraphics.GraphicsDevice.SetRenderTarget(mFogOfWarRT);
        }
        //important both stencil states be created in their own object, cannot modify once set for some reason.
        DepthStencilState lState = new DepthStencilState();
        lState.StencilEnable = true;
        lState.StencilFunction = CompareFunction.Always;
        lState.ReferenceStencil = 1;
        lState.StencilPass = StencilOperation.Replace;
        lState.DepthBufferEnable = false;
        pGraphicsDevice.Clear(ClearOptions.Target | ClearOptions.Stencil,
                                  new Color(0, 0, 0, 1), 0, 0);
        pSpriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, null, lState, null, alphaTestEffect);
        foreach (ClearArea lArea in mDrawQueue)
        {
//draw whatever you want "visible" anything in the texture with an alpha of 0 will be allowed to draw.
            pSpriteBatch.Draw(mAlphaMask, new Rectangle((int)lArea.X, lArea.Y, lArea.Diameter, lArea.Diameter), Color.White);
        }

        pSpriteBatch.End();

        // Draw minimap texture
        DepthStencilState lState2 = new DepthStencilState();
        lState2.StencilEnable = true;
        lState2.StencilFunction = CompareFunction.Equal;
        lState2.ReferenceStencil = 0;
        lState2.StencilPass = StencilOperation.Keep;
        lState2.DepthBufferEnable = false;

        pSpriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, null, lState2, null);
        pSpriteBatch.Draw(mDot, new Rectangle(0, 0, 400, 400), Color.Black);

        pSpriteBatch.End();
        //done drawing to the render target
        pGraphicsDevice.SetRenderTarget(null);
        pGraphicsDevice.Clear(Color.Gray);
        pSpriteBatch.Begin();
        pSpriteBatch.Draw(mDot, new Rectangle(0, 0, 400, 400), Color.Blue);
        pSpriteBatch.Draw(mFogOfWarRT,Vector2.Zero,Color.White);
        pSpriteBatch.End();