2010-05-18 23 views
9

Ekrandaki müzikçalara, müzikçalarda halihazırda görünür olmayan bir yere sis atmaya çalışıyorum. Bunu oyunun içeriğini bir RenderTarget ve savaşın sisini bir diğerine dönüştürerek yapıyorum ve sonra onları oyunun rengi RenderTarget ve alfa savaşı hedefin hedefi olan alfadan alan bir efekt dosyasıyla birleştiriyorum. FOW RenderTarget, FOW'un göründüğü yerde siyah ve olmadığı yerde beyazdır.Sis Sisli için Efekt Kullanma

Bu işe yarıyor, ancak amaçlanan renkteki siyahın yerine beyazın (ortaya çıkarılmamış konumlar) beyazını renklendiriyor.

Efekt uygulamadan önce, cihazın arka tarafını beyaza doğru siliyorum. Siyahı temizlemeye çalıştığımda, savaşın hiç bir sisini göremiyorum, ki bu siyahla alfa harmanlamanın bir ürünüdür. Bununla birlikte, diğer tüm renkler için çalışır, sonuçta ortaya çıkan ekrana bu rengin bir tonu verilir.

İki render hedefi arasında hala alfa harmanlamayı yaparken siyah bir sisteği nasıl arşivlerim?

Fow uygulamak için render kodu:

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(); 
    } 

Ben Fow uygulamak için kullanıyorum etkisi dosyası: Eğer duruma çalışan gibi

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(); 
    } 
} 

cevap

3

XNA'ya çok fazla bakmadım ve şu anda CTP'nin 4.0'ını kontrol etmek için ayarlayamıyorum. iki katına çıkıyorum. Anlayışımdan, BlendState.AlphaBlend, çizilen her hareketli grafiği alfa harmanlamak için SpriteBatch neden olur.

documentation göre, impact aşağıdaki olmalıdır

ColorSourceBlend = Blend.One, 
AlphaSourceBlend = Blend.One, 

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

varsayılan ayarları kullanır:

Bir: rengin her bölümü (1, 1 ile çarpılır 1, 1).

InverseSourceAlpha: renk kaynağının alfa değerinin ters ile çarpılır bileşenlerinin her biri. Bu , (1 - As, 1 - As, 1 - As, 1 - As) olarak gösterilebilir; burada As, alfa hedef değeridir. Eğer Blend.AlphaBlend kullanıyorsanız

Yani siyah için geri tampon temizlemek gerekir ve daha sonra sadece doğrudan o soluk edilmelidir alfa düşürücü, haritanız sprite işlemek. Bu, harita piksellerini FOW tarafından 'kapsanan' olarak tersine çevirmeli ve alfa tamponunun siyahı ile harmanlanmasını sağlamalıdır.

Gölgelendirici yaklaşımını kullanmak isterseniz, alfadaki gölgeyi iki render hedefi arasında karıştırabilirsiniz.Tam olarak nasıl uyum sağladığına dair açıklamandan biraz kafam karıştı. Alfa harmanı yapmak istediğinizi söylüyorsunuz, ancak FOW'un render hedefiniz, olmadığı yerde sis ve beyaz olan yerlerde siyahtır. Karışımı kontrol etmek için alfa kullanıyorsanız, sis renginiz, istediğiniz görünüme göre tüm render hedefi boyunca düzgün (veya uygun şekilde dokulu) olmalıdır. Siyah sis istediğinizi söyleyin, tüm render hedefi boyunca renklerin (0, 0, 0) olmalıdır ve alfa değeri göstermek istediğiniz yere göre değişmelidir. Aşağıdaki gibi bir şey için gölgelendiricisini değiştirebilir Bu yaklaşımı kullanarak

:

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); 
} 

Bir süre HLSL gölgelendiricileri yapmadım ama bu çok daha kolay yazılabilir eminim. Her iki durumda da, FOW siyahsa (ve arka tampon siyah olarak silinirse ve birbirinin üzerine çeşitli alfa harmanlanmış spritelar yerleştirmiyorsanız - Joel'in cevabına bakın), bu yaklaşımın doğrudan alfa değerinin ayarlanmasından farklı değildir. FOW olsun ya da olmasın harita sprite.

+0

Çok faydalı yanıt. Alfa ve harman kavramlarını karıştırdım. LightTarget RT'm artık görünür alanlarda şeffaftır ve her yerde tamamen opaktır. Bu, fow çizmek için gölgelendiricinizin değiştirilmiş bir sürümünü kullanmamı sağlar. Color.r * yerine (1-fow.a) fow.r kullanıyorum * (1-fow.a). –

İlgili konular