2010-05-18 74 views
9

我試圖將戰爭迷霧應用到屏幕上當前對玩家不可見的區域。我通過將一個RenderTarget中的遊戲內容和戰爭迷​​霧中的遊戲內容渲染爲另一個,然後將它們與一個效果文件合併,該效果文件將遊戲RenderTarget中的顏色和來自戰爭迷霧中的alpha渲染目標合併。 FOW RenderTarget在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(); 
    } 
} 

回答

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:顏色是由所述源的α值的倒數乘以 的 每個組件。這個 可以表示爲(1-As,1-As, 1-As,1-As),其中As是阿爾法 目的地值。

所以,如果你使用Blend.AlphaBlend你應該能夠清除後緩衝區爲黑色,然後只渲染地圖精靈,直接降低了它應該褪色的阿爾法。這應該簡單地淡化由FOW'覆蓋'的地圖像素,導致它與後緩衝區的黑色混合。

如果你想採用着色器方法,你可以在兩個渲染目標之間的着色器中混合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的回答),但這種方法與直接設置基於是否存在FOW來映射精靈。

+0

非常有用的答案。我有一個概念alpha和混合搞砸了。我的LightTarget RT現在在可見區域是透明的,在其他地方是完全不透明的黑色。這使我可以使用着色器的修改版本來繪製fow。而不是color.r *(1-fow.a)我使用fow.r *(1-fow.a)。 – 2010-05-18 22:35:08