URP的后处理入门

331 阅读3分钟

URP的后处理还是比较的复杂的,我在了解了一些URP的管线中参考视频【Free Bird/URP教学】6.URP后处理_哔哩哔哩_bilibili写出本篇的文章,共自己后面的学习和总结。

volume组件

在后处理的过程中,为了更好的操控后处理的效果,需要暴露一些参数和结果给用户,所以需要写一个脚本来添加这些数据:

using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;

public class ColorTint : VolumeComponent
{
    //【设置颜色参数】
    public ColorParameter colorChange = new ColorParameter(Color.white, true);//如果有两个true,则为HDR设置
}


//这个是volume的设置,为volumecomponent组件添加color参数,并且colorTint和下面的参数都暴露出来

该脚本需要放置在volume的组件,下这里只是设置了一个颜色的参数:效果如下:

1. 1703061710470.png

在后面更改效果的时候使用这个可以更改需要的选项。

ScriptableRendererFeature

这个是主要用来写目的的后处理的脚本的代码,主要通过ScriptableRendererFeature类和渲染类ScriptableRenderPass来实现,基本的渲染流程已经注释完成:

using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;

public class ColorTintRenderFeature : ScriptableRendererFeature
{
    [System.Serializable]
    public class Settings
    {
        public RenderPassEvent renderPassEvent = RenderPassEvent.BeforeRenderingPostProcessing;//在后处理前执行我们的颜色校正
        public Shader shader;//汇入shader
    }
    public Settings settings = new Settings();//开放设置


    ColorTintPass colorTintPass;//设置渲染pass
    public override void Create()//新建pass
    {
        this.name = "ColorTintPass";     //名字,本身是public,可以显示在外面
        colorTintPass = new ColorTintPass(RenderPassEvent.BeforeRenderingPostProcessing,settings.shader);//初始化
    }
    public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)//Pass逻辑
    {
        renderer.EnqueuePass(colorTintPass);//汇入队列
    }
    public override void SetupRenderPasses(ScriptableRenderer renderer, in RenderingData renderingData)
    {
        colorTintPass.Setup(renderer.cameraColorTargetHandle);
    }



    //【执行pass】
    public class ColorTintPass : ScriptableRenderPass
    {
        static readonly string k_RenderTag = "ColorTint Effects";//设置tags
        static readonly int MainTexId = Shader.PropertyToID("_MainTex");//设置主贴图
        static readonly int TempTargetId = Shader.PropertyToID("_TempTargetColorTint");//设置暂存贴图

        ColorTint colorTint;//提供一个Volume传递位置
        Material colorTintMaterial;//后处理使用材质
        RenderTargetIdentifier currentTarget;//设置当前渲染目标

        #region 设置渲染事件
        public ColorTintPass(RenderPassEvent evt, Shader ColorTintShader)
        {
            renderPassEvent = evt;//设置渲染事件位置
            var shader = ColorTintShader;//汇入shader
                                         //不存在则返回
            if (shader == null)
            {
                Debug.LogError("不存在ColorTint shader");
                return;
            }
            colorTintMaterial = CoreUtils.CreateEngineMaterial(ColorTintShader);//新建材质
        }
        #endregion

        #region 初始化
        public void Setup(in RenderTargetIdentifier currentTarget)
        {

            this.currentTarget = currentTarget;
        }
        #endregion

        #region 执行
        public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
        {
            if (colorTintMaterial == null)//材质是否存在
            {
                Debug.LogError("材质初始化失败");
                return;
            }
            //摄像机关闭后处理
            if (!renderingData.cameraData.postProcessEnabled)
            {
                return;
            }
            //【渲染设置】
            var stack = VolumeManager.instance.stack;//传入volume数据
            colorTint = stack.GetComponent<ColorTint>();//拿到我们的Volume
            if (colorTint == null)
            {
                Debug.LogError("Volume组件获取失败");
                return;
            }

            var cmd = CommandBufferPool.Get(k_RenderTag);//设置抬头
            Render(cmd, ref renderingData);//设置渲染函数
            context.ExecuteCommandBuffer(cmd);//执行函数
            CommandBufferPool.Release(cmd);//释放
        }
        #endregion

        #region 渲染
        void Render(CommandBuffer cmd, ref RenderingData renderingData)
        {
            ref var cameraData = ref renderingData.cameraData;//汇入摄像机数据
            var camera = cameraData.camera;//传入摄像机数据
            var source = currentTarget;//当前渲染图片汇入
            int destination = TempTargetId;//渲染目的地

            colorTintMaterial.SetColor("_ColorTint", colorTint.colorChange.value);//汇入颜色校正,来自colorTnt的颜色值

            cmd.SetGlobalTexture(MainTexId, source);//汇入当前渲染图片,把sourece给以maintexid
            cmd.GetTemporaryRT(destination, cameraData.camera.scaledPixelWidth, cameraData.camera.scaledPixelHeight, 0, FilterMode.Trilinear, RenderTextureFormat.Default);//设置目标贴图
            cmd.Blit(source, destination,colorTintMaterial,0);//设置后处理,渲染到暂是保存的纹理
            cmd.Blit(destination, source, colorTintMaterial, 0);//传入颜色校正,0表示默认使用的着色器通道,采用的是双缓冲
        }
        #endregion
    }

}

主要就是在feature中创建一个渲染的流程,和一个渲染的类,实现渲染。通过setting也暴露一部分的接口:

1703062156511.png

## shader 下面是着色器的代码
Shader "PostProcess/ColorTint"//名字开放位置
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}   //外部的输入的纹理
    }
    SubShader
    {
        Tags { "RenderPipeline"="UniversalPipeline" }
        Cull Off ZWrite Off ZTest Always

        Pass
        {
            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            float4 _ColorTint;              //设置颜色校正位置

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = TransformObjectToHClip(v.vertex);//裁剪空间转换
                o.uv = v.uv;
                return o;
            }

            float4 frag (v2f i) : SV_Target
            {
                // sample the texture
                float4 col = tex2D(_MainTex, i.uv) * _ColorTint;   //进行颜色矫正
                // apply fog
                return col;
            }
            ENDHLSL
        }
    }
}

在该sahder代码拖入就可以实现了,需要说明的是,本版本使用的是urp14. 基本效果有:

1703062833629.png