2014-02-25 199 views
0

我正在嘗試爲基於MonoGame的2D遊戲添加陰影。起初我只是呈現半透明的黑色紋理的框架,但它們有時重疊,它看起來討厭:MonoGame:模板緩衝區不起作用

Sample render with overlapping shadows

我想首先渲染所有陰影到模板緩存,然後使用一個半透明紋理使用模板緩衝區一次繪製所有陰影。但是,按預期它不工作:

Stencil buffer render

的兩個問題是:

  • 陰影渲染到場景
  • 模板緩衝區是看似不受影響:半透明黑色紋理覆蓋整個屏幕

這裏是初始化代碼:

StencilCreator = new DepthStencilState 
{ 
    StencilEnable = true, 
    StencilFunction = CompareFunction.Always, 
    StencilPass = StencilOperation.Replace, 
    ReferenceStencil = 1 
}; 

StencilRenderer = new DepthStencilState 
{ 
    StencilEnable = true, 
    StencilFunction = CompareFunction.Equal, 
    ReferenceStencil = 1, 
    StencilPass = StencilOperation.Keep 
}; 

var projection = Matrix.CreateOrthographicOffCenter(0, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height, 0, 0, 1); 
var halfPixel = Matrix.CreateTranslation(-0.5f, -0.5f, 0); 

AlphaEffect = new AlphaTestEffect(GraphicsDevice) 
{ 
    DiffuseColor = Color.White.ToVector3(), 
    AlphaFunction = CompareFunction.Greater, 
    ReferenceAlpha = 0, 
    World = Matrix.Identity, 
    View = Matrix.Identity, 
    Projection = halfPixel * projection 
}; 

MaskingTexture = new Texture2D(GameEngine.GraphicsDevice, 1, 1); 
MaskingTexture.SetData(new[] { new Color(0f, 0f, 0f, 0.3f) }); 

ShadowTexture = ResourceCache.Get<Texture2D>("Skins/Common/wall-shadow"); 

而下面的代碼是我Draw方法的主體:

// create stencil 
GraphicsDevice.Clear(ClearOptions.Stencil, Color.Black, 0f, 0); 
var batch = new SpriteBatch(GraphicsDevice); 
batch.Begin(SpriteSortMode.Immediate, null, null, StencilCreator, null, AlphaEffect); 
foreach (Vector2 loc in ShadowLocations) 
{ 
    newBatch.Draw(
     ShadowTexture, 
     loc, 
     null, 
     Color.White, 
     0f, 
     Vector2.Zero, 
     2f, 
     SpriteEffects.None, 
     0f 
    ); 
} 
batch.End(); 

// render shadow texture through stencil 
batch.Begin(SpriteSortMode.Immediate, null, null, StencilRenderer, null); 
batch.Draw(MaskingTexture, GraphicsDevice.Viewport.Bounds, Color.White); 
batch.End(); 

怎麼可能是什麼問題?在我的XNA項目中,相同的代碼工作正常。

回答

0

我通過使用RenderTarget2D而不是模板緩衝區來解決問題。將純黑色陰影繪製到RT2D上,然後使用半透明顏色將RT2D本身繪製到場景中,這樣做的竅門並且實現起來非常簡單。