C#/ XNA/HLSL - 如何创建景深?

Jar*_*red 0 c# xna hlsl

我正在尝试创建一个景深后期处理,但不知道从哪里开始(除了渲染深度图,我目前正在).它的所有教程都是针对XNA3.1,实际上没有给你解释,或者是书的一部分.

那么,您是否可以通过详细的逐步过程来了解DOF的呈现方式?

lzc*_*zcd 8

以下是使用XNA在Reach配置文件中提供的"开箱即用"功能实现基本近似的描述.

一旦你使用内置的东西在C#中进行如何操作,在HLSL中实现它将有希望更加明显.

此外,如果您希望为Windows Phone 7制作游戏,您将从哪里开始(因为此时Windows Phone 7不支持自定义着色器).

首先,我们将定义一些实例级变量来保存我们生成外观所需的位数:

BasicEffect effect;
List<Matrix> projections;
List<RenderTarget2D> renderTargets;
SpriteBatch spriteBatch;
Run Code Online (Sandbox Code Playgroud)

接下来,在LoadContent()方法中,我们将开始加载它们.从我们将用于渲染最终场景的SpriteBatch开始:

spriteBatch = new SpriteBatch(GraphicsDevice);
Run Code Online (Sandbox Code Playgroud)

接下来是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();
Run Code Online (Sandbox Code Playgroud)

如何配置基本效果的细节在这里并不重要.仅仅是我们有效渲染.

接下来我们需要一些投影矩阵:

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)};
Run Code Online (Sandbox Code Playgroud)

如果你检查每个投影的最后两个参数,你会注意到我们在这里有效地做的是将世界分成"块",每个块覆盖与摄像机不同的距离范围.

例如,从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),
};
Run Code Online (Sandbox Code Playgroud)

每个渲染目标对应于前述的"块".为了实现非常简单的模糊效果,每个渲染目标被设置为不同的分辨率,其中"最远"的块是低分辨率而最接近的块是高分辨率.

跳转到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);
Run Code Online (Sandbox Code Playgroud)

所以现在我们已经得到了我们的场景,被打破并且被距离模糊了,剩下的就是将它重新组合在一起以获得我们的最终图像.

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

    GraphicsDevice.Clear(Color.CornflowerBlue);
Run Code Online (Sandbox Code Playgroud)

接下来渲染每个块,从进一步到最近:

    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();
Run Code Online (Sandbox Code Playgroud)

而且中提琴!我们有一个,虽然有点粗糙的谚语边缘,近似的景深.

现在,如果您计划保持在Reach配置文件的范围内,可以通过渲染多个分辨率的每个块并使用Additive BlendState之类的结果将结果图像组合在一起来改善模糊效果.

另一方面,如果您计划在HiDef配置文件中分支编写自定义着色器,则概念大致相同,只是执行更改的方法.

例如,交换低分辨率渲染以获得更真实的高斯风格模糊...或者......放弃课程的粒度理念并根据深度图移动到相对细粒度的模糊方法.