Unity自定义SRP(十四):抗锯齿和缩放渲染

1 MSAA

SRP中实现MSAA很简单。我们先在CustomRenderPipelienAsset中添加对应的枚举,MSAA默认关闭:

    public enum MSAAMode
    {
        Off = 1,
        _2x = 2,
        _4x = 4,
        _8x = 8
    }

    [SerializeField]
    MSAAMode MSAA = MSAAMode.Off;

CameraRenderer中,我们和后处理效果一块使用即可。在Setup中,如果开启后处理模块,我们设置MSAA采样数,并将其应用到我们的渲染目标的声明,位于最后一个参数中:

void Setup(int MSAA)
    {
        ...

        if(postFXStack.IsActive)
        {
            int renderSamples = camera.allowMSAA ? MSAA : 1;
            if (flags > CameraClearFlags.Color)
            {
                flags = CameraClearFlags.Color;
            }
            buffer.GetTemporaryRT(frameBufferId, bufferSize.x, bufferSize.y, 32,
                FilterMode.Bilinear, useHDR ? RenderTextureFormat.DefaultHDR : RenderTextureFormat.Default, 
                RenderTextureReadWrite.Default, renderSamples);
            buffer.SetRenderTarget(frameBufferId, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store);
        }

默认采样数为1,如果设置了MSAA,那么使用对应的采样数。

关闭MSAA和4xMSAA:



目前的MSAA只处理了颜色缓冲,如果想应用于深度我们需要分开设置。

注意MSAA想得到较好的效果是比较耗能的,之后会尝试增加TAA之类的抗锯齿方法。

2 缩放渲染

缩放渲染可用于调整渲染的分辨率。在CustomRenderPipelienAsset中添加相应的浮点变量:

    [SerializeField]
    float RenderScale = 1f;

CameraRenderer中,我们添加一个布尔变量来确定是否使用缩放渲染:

    bool useScaledRendering;

Render中确定是否使用缩放:

        useScaledRendering = renderScale < 0.99f || renderScale > 1.01f;

注意在编辑器窗口中我们就不使用缩放了,以免耗能,在PrepareForSceneWindow中将布尔值设为false:

    partial void PrepareForSceneWindow()
    {
        if (camera.cameraType == CameraType.SceneView)
        {
            ScriptableRenderContext.EmitWorldGeometryForSceneView(camera);
            useScaledRendering = false;
        }
    }

如果设置缩放渲染的话,就使用缩放数值调整缓冲大小,否则使用原摄像机的视口大小即可:

        if(useScaledRendering)
        {
            bufferSize.x = (int)(camera.pixelWidth * renderScale);
            bufferSize.y = (int)(camera.pixelHeight * renderScale);
        }
        else
        {
            bufferSize.x = camera.pixelWidth;
            bufferSize.y = camera.pixelHeight;
        }

Setup中应用,调整渲染目标的缓冲大小:

            buffer.GetTemporaryRT(frameBufferId, bufferSize.x, bufferSize.y, 32,
                FilterMode.Bilinear, useHDR ? RenderTextureFormat.DefaultHDR : RenderTextureFormat.Default, 
                RenderTextureReadWrite.Default, renderSamples);

Render中,我们也将缓冲大小传入postFXStack.Setup中。对于发光效果,我们可以设置一个布尔值来控制是否引用缩放,在PostFXSettings中设置BloomSettings结构体:

public bool ignoreRenderScale;

DoBloom中,根据是否忽略缩放来调整缓冲大小:

        int width, height;
        if (bloom.ignoreRenderScale)
        {
            width = camera.pixelWidth / 2;
            height = camera.pixelHeight / 2;
        }
        else
        {
            width = bufferSize.x / 2;
            height = bufferSize.y / 2;
        }

对应的地方应用即可。

对于后处理,我们额外添加一个缩放pass来进行渲染缩放:

        Pass {
            Name "Final Rescale"
            
            HLSLPROGRAM
                #pragma target 3.5
                #pragma vertex DefaultPassVertex
                #pragma fragment CopyPassFragment
            ENDHLSL
        }

一个很简单的复制pass。

DoColorGradingAndToneMapping的最后,根据缓冲大小的设置决定使用不同的pass:

        if(bufferSize.x == camera.pixelWidth)
        {
            DrawFinal(sourceId, Pass.Final);
        }
        else
        {
            buffer.GetTemporaryRT(finalResultId, bufferSize.x, bufferSize.y, 0,
                FilterMode.Bilinear, RenderTextureFormat.Default);
            Draw(sourceId, finalResultId, Pass.Final);
            DrawFinal(finalResultId, Pass.FinalRescale);
            buffer.ReleaseTemporaryRT(finalResultId);
        }

0.5和2:



推荐阅读更多精彩内容