2012-04-04 47 views
0

我試圖創建一個景深後期過程,但不知道從哪裏開始(除了渲染深度圖,我目前在)。所有的教程都是針對XNA3.1的,實際上並沒有給你一個解釋,或者是一本書的一部分。C#/ XNA/HLSL - 如何創建景深?

那麼,您可以詳細瞭解如何渲染DOF的詳細步驟嗎?

回答

8

下面是關於如何使用XNA在Reach配置文件中提供的「開箱即用」功能對其進行基本近似的描述。

一旦你瞭解如何在C#中使用內置的東西來實現它,在HLSL中實現它將有希望變得更加明顯。此外,如果您希望爲Windows Phone 7製作遊戲,您可以從哪裏開始(因爲Windows Phone 7此時不支持自定義着色器)。

首先,我們定義一些實例級別變量來保存我們需要製作外觀的點點滴滴:

BasicEffect effect; 
List<Matrix> projections; 
List<RenderTarget2D> renderTargets; 
SpriteBatch spriteBatch; 

接下來,在LoadContent()方法中,我們將開始加載它們。

spriteBatch = new SpriteBatch(GraphicsDevice); 

其次是BasicEffect的一個實例:

effect = new BasicEffect(GraphicsDevice); 
effect.EnableDefaultLighting(); 
effect.DiffuseColor = Color.White.ToVector3(); 
effect.View = Matrix.CreateLookAt(
      Vector3.Backward * 9 + Vector3.Up * 9, 
      Vector3.Zero, 
      Vector3.Up); 
effect.World = Matrix.Identity; 

effect.Texture = Content.Load<Texture2D>("block"); 
effect.TextureEnabled = true; 
effect.EnableDefaultLighting(); 

的基本作用是如何配置的細節並非是與將我們用來渲染的最後一幕一個SpriteBatch啓動這裏很重要。只是我們有一個效果來渲染。

接下來,我們會需要幾個投影矩陣:

projections = new List<Matrix>() { 
     Matrix.CreatePerspectiveFieldOfView(
     MathHelper.ToRadians(60f), 
     GraphicsDevice.Viewport.AspectRatio, 
     9f, 
     200f), 
    Matrix.CreatePerspectiveFieldOfView(
     MathHelper.ToRadians(60f), 
     GraphicsDevice.Viewport.AspectRatio, 
     7f, 
     10f), 
    Matrix.CreatePerspectiveFieldOfView(
     MathHelper.ToRadians(60f), 
     GraphicsDevice.Viewport.AspectRatio, 
     0.2f, 
     8f)}; 

如果檢查每個投影的最後兩個參數,你會發現我們正在有效這裏做的是分裂這個世界分成「塊」,每個塊覆蓋與相機不同的距離範圍。

例如一切從9個單位以外,任何7個單位和10個單位從相機,最後任何接近8個單位。

(你需要調整這些距離取決於你的場景,請注意少量的重疊。)

接下來,我們將創建一些渲染目標:

var pp = GraphicsDevice.PresentationParameters; 

renderTargets = new List<RenderTarget2D>() 
{ 
    new RenderTarget2D(GraphicsDevice, 
     GraphicsDevice.Viewport.Width/8, 
     GraphicsDevice.Viewport.Height/8, 
     false, pp.BackBufferFormat, pp.DepthStencilFormat), 

     new RenderTarget2D(GraphicsDevice, 
     GraphicsDevice.Viewport.Width/4, 
     GraphicsDevice.Viewport.Height/4, 
     false, pp.BackBufferFormat, pp.DepthStencilFormat), 

    new RenderTarget2D(GraphicsDevice, 
     GraphicsDevice.Viewport.Width, 
     GraphicsDevice.Viewport.Height, 
     false, pp.BackBufferFormat, pp.DepthStencilFormat), 
}; 

每個渲染目標對應到前面提到的「塊」。爲了達到真正簡單的模糊效果,每個渲染目標都設置爲不同的分辨率,「最遠」的塊是低分辨率,最接近的塊是高分辨率。

跨越跳轉到Draw()方法中,我們可以使我們的場景塊: (即確保不使在每個塊的背景)

 effect.Projection = projections[0]; 
     GraphicsDevice.SetRenderTarget(renderTargets[0]); 
     GraphicsDevice.Clear(Color.Transparent); 
     // render scene here 

     effect.Projection = projections[1]; 
     GraphicsDevice.SetRenderTarget(renderTargets[1]); 
     GraphicsDevice.Clear(Color.Transparent); 
     // render scene here 

     effect.Projection = projections[2]; 
     GraphicsDevice.SetRenderTarget(renderTargets[2]); 
     GraphicsDevice.Clear(Color.Transparent); 
     // render scene here 

     GraphicsDevice.SetRenderTarget(null); 

現在,我們已經得到了我們的現場,破碎因距離而變得模糊,剩下的就是將它重新組合在一起以獲得最終的圖像。

第一步,渲染(真棒)背景:

GraphicsDevice.Clear(Color.CornflowerBlue); 

下使每個塊,進一步最接近:

spriteBatch.Begin(
     SpriteSortMode.Deferred, 
     BlendState.AlphaBlend, 
     SamplerState.AnisotropicClamp, 
     null, null); 

    spriteBatch.Draw(renderTargets[0], GraphicsDevice.Viewport.Bounds, Color.White); 
    spriteBatch.Draw(renderTargets[1], GraphicsDevice.Viewport.Bounds, Color.White); 
    spriteBatch.Draw(renderTargets[2], GraphicsDevice.Viewport.Bounds, Color.White); 

    spriteBatch.End(); 

和中提琴!我們有一個,雖然有點粗糙圍繞諺語的邊緣,逼近景深。

現在,如果您打算保留在Reach配置文件的範圍內,可以通過以多種分辨率呈現每個塊並使用類似於Additive BlendState的組合結果圖像來改善模糊效果。

另一方面,如果您計劃在HiDef配置文件中分支編寫自定義着色器,則概念大致相同,只是執行更改的方法。

例如,交換低分辨率渲染以獲得更真實的高斯樣式模糊......或者...切掉塊的粗糙概念並移至基於深度圖的相對精細的模糊方法。