我试图为战争迷雾建立一个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();
对此的任何帮助都会非常感激..
完整代码的粘贴箱
如果需要,可以获得结果的屏幕截图。
答案 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();