战争迷雾的效果

时间:2010-05-18 01:11:45

标签: c# .net xna effects

我正在尝试将战争雾应用于屏幕上目前玩家无法看到的区域。我通过将游戏内容渲染到一个RenderTarget并将战争迷雾转换为另一个来实现这一点,然后我将它们与一个效果文件合并,该文件采用游戏RenderTarget的颜色和来自游戏的alpha。战争迷雾渲染目标。 FOW RenderTarget在FOW出现时为黑色,而在FOW出现时为白色。

这确实有效,但它会将战争迷雾(未显示的位置)变成白色,而不是黑色的预期颜色。

在应用效果之前,我将设备的后备缓冲区清除为白色。当我试图将它清除为黑色时,根本没有出现战争迷雾,我认为这是alpha混合黑色的产物。但它适用于所有其他颜色 - 为结果屏幕提供该颜色的色调。

如何在能够在两个渲染目标之间进行Alpha混合的同时实现黑雾?

应用FOW的渲染代码:

private RenderTarget2D mainTarget;
private RenderTarget2D lightTarget;

   private void CombineRenderTargetsAndDraw()
    {
        batch.GraphicsDevice.SetRenderTarget(null);
        batch.GraphicsDevice.Clear(Color.White);

        fogOfWar.Parameters["LightsTexture"].SetValue(lightTarget);

        batch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend);
        fogOfWar.CurrentTechnique.Passes[0].Apply();
        batch.Draw(
            mainTarget,
            new Rectangle(0, 0, batch.GraphicsDevice.PresentationParameters.BackBufferWidth, batch.GraphicsDevice.PresentationParameters.BackBufferHeight),
            Color.White
        );

        batch.End();
    }

我用来应用FOW的效果文件:

texture LightsTexture;

sampler  ColorSampler  : register(s0);

sampler LightsSampler = sampler_state{
    Texture = <LightsTexture>;
};

struct VertexShaderOutput
{
    float4 Position : POSITION0;
    float2 TexCoord : TEXCOORD0;
};

float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
    float2 tex = input.TexCoord;

    float4 color = tex2D(ColorSampler, tex);
    float4 alpha = tex2D(LightsSampler, tex);

    return float4(color.r, color.g, color.b, alpha.r);
}

technique Technique1
{
    pass Pass1
    {
        PixelShader = compile ps_2_0 PixelShaderFunction();
    }
}

2 个答案:

答案 0 :(得分:3)

我没有深入研究XNA并且目前无法设置它来检查4.0的CTP,但是从阅读文档看起来你看起来已经翻倍了。根据我的理解,BlendState.AlphaBlend会导致SpriteBatch与alpha混合绘制的每个精灵。

根据documentation,它使用

的默认设置
ColorSourceBlend = Blend.One,
AlphaSourceBlend = Blend.One,

ColorDestinationBlend = Blend.InverseSourceAlpha,
AlphaDestinationBlend = Blend.InverseSourceAlpha,

哪个应该有以下impact

  

一个:颜色的每个分量都乘以(1,1,1,1)。

     

InverseSourceAlpha :每个组件   颜色乘以逆   源的alpha值。这个   可以表示为(1 - As,1 - As,   1 - As,1 - As),其中As是alpha   目的地价值。

因此,如果你正在使用Blend.AlphaBlend,你应该能够将你的后台缓冲区清除为黑色,然后只渲染你的地图精灵,直接降低应该褪色的alpha值。这应该简单地淡化FOW“覆盖”的地图像素,使其与后面缓冲区的黑色进行alpha混合。

如果要采用着色器方法,可以在两个渲染目标之间的着色器中进行Alpha混合。我对你究竟想要如何融合的解释感到有些困惑。你说你想要alpha混合,但你的FOW渲染目标是黑色,有雾,而白色没有。如果您使用alpha来控制混合,则您的雾颜色应该在整个渲染目标上均匀(或根据需要进行纹理化),具体取决于您想要的外观。假设你想要黑雾,你的颜色应该是整个渲染目标的(0,0,0),并且alpha值应该根据你想要显示它的位置而改变。

使用此方法,您可以将着色器更改为以下内容:

float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
    float2 tex = input.TexCoord;

    float4 color = tex2D(ColorSampler, tex);
    float4 fow = tex2D(LightsSampler, tex);

    // color * inverse of FOW alpha + FOW * FOW alpha
    return float4(color.r * (1-fow.a) + fow.r * fow.a,
                  color.g * (1-fow.a) + fow.g * fow.a,
                  color.b * (1-fow.a) + fow.b * fow.a,
                  1);
}

我有一段时间没有完成HLSL着色器,但我确信可以写得更容易。无论哪种方式,如果FOW是黑色的(并且后面的缓冲区被清除为黑色,并且你没有将各种alpha混合的精灵堆叠在一起 - 请参阅Joel的答案),这种方法与直接设置alpha的alpha无异。根据是否有FOW来映射精灵。

答案 1 :(得分:1)

听起来你正在遇到Shawn Hargreaves在这篇博文中描述的情况:
Premultiplied Alpha and Image Composition

尝试按照他的建议切换到pre-multiplied alpha并让我们知道结果: - )

相关问题