URP---自定义后处理流程

URP—自定义后处理流程
前记:默认的build-in管线的后处理挺简单,但是换了urp还想上后处理,使用这几天进行了学习---------------------mx

屏幕后处理:通常指在渲染完整个场景得到屏幕图像之后再对这个图像进行一系列操作,实现各种屏幕特效。

在build-in的管线中,后处理的基本流程是:

  1. 预处理—用于提前检查各种资源和条件是否满足
  2. 在OnRenderImage函数中对shader中的变量进行赋值,并根据shader对源图像进行处理

URP后处理前期准备
在包管理器中导入Universal RP,右键创建Assets/Create/Rendering/Universal Render Pipeline/Pipeline Asset
URP---自定义后处理流程_第1张图片
这里可以加入自定义的后处理

然后在设置中修改当前可编写脚本的渲染管线设置,改为刚才创建的pipeline

然后右键创建Assets/Create/Rendering/Universal Render Pipeline/RendererFeature,会出现一个脚本里面有两个类分别继承了ScriptableRendererFeature,ScriptableRenderPass

我们先来了解一下继承了ScriptableRendererFeature的类吧

  1. 首先public的变量都会在资产面板中显示
    在这里插入图片描述在这里插入图片描述
    2.需要重写的Create函数是在RendererFeature被创建时调用,这个方法里通常实现的功能是实例化那个继承了ScriptableRenderPass的类
    在这里插入图片描述
    3.需要重写的AddRenderPasses函数是渲染的每一帧都会调用,通常做的就是把当前已经渲染出来的RenderTexture传入到继承了ScriptableRenderPass的类(对自定义的Pass进行初始化),然后在Renderer插入那个继承了ScriptableRenderPass的类
    URP---自定义后处理流程_第2张图片

    4.其他:如Dispose函数是在一帧执行完之后调用

然后看一下继承了ScriptableRenderPass的类

  1. 这个类是实际的渲染工作,这个类可以加入一个RenderPassEvent来控制Pass执行的时间点,来控制每个Pass的执行顺序
  2. 这个类有一个可以重写的方法Configure函数,在执行渲染过程之前,Renderer将调用此方法,如果要配置渲染目标以及清楚状态,创建里临时的渲染目标纹理就需要重写这个方法。如果渲染过程没有重写这个方法,那么这个渲染过程将会渲染到已经激活的Camera渲染目标下
  3. 这个类重写的方法Execute函数,是这个类的核心方法,是执行方法,可以定义我们的执行规则,常用是用我们自己写的shader来处理当前的RenderTexture然后输出到一张临时创建的RenderTexture,最后再把当前处理后的RenderTexture输出到屏幕上
    URP---自定义后处理流程_第3张图片
  4. 可以重写的FrameCleanup函数在完成当前帧渲染后,调用,用于回调释放渲染过程中创建的所有资源URP---自定义后处理流程_第4张图片
  5. 我们可以自己写一个setup函数用于接收继承了ScriptableRendererFeature的类传入的变量,然后对shader中公开的变量进行初始化
    URP---自定义后处理流程_第5张图片
  6. 注意new Material(Shader.Find(“shader名称”))这个shader名称就是shader代码中第一行的名称;

实战:做一个可以改变屏幕亮度、饱和度、对比度的后处理

后处理脚本

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

public class Test : ScriptableRendererFeature
{
    public class RendererPassTest : ScriptableRenderPass
    {

        Material m_Mat = new Material(Shader.Find("Custom/PostEffect"));

        //RT的Filter
        public FilterMode filterMode { get; set; }

        //当前阶段渲染的颜色RT
        RenderTargetIdentifier m_Source;

        //辅助RT
        RenderTargetHandle m_TemporaryColorTexture;

        //Profiling上显示
        ProfilingSampler m_ProfilingSampler = new ProfilingSampler("URPTest");

        public RendererPassTest()
        {
            //在哪个阶段插入渲染
            renderPassEvent = RenderPassEvent.AfterRenderingOpaques;

            //初始化辅助RT名字
            m_TemporaryColorTexture.Init("URPBaseTest");
        }

        public void Setup(RenderTargetIdentifier source, float brightness, float saturate, float contranst)
        {
            m_Source = source;
            //m_Color = color;
            m_Mat.SetFloat("_brightness", brightness);
            m_Mat.SetFloat("_saturate", saturate);
            m_Mat.SetFloat("_contranst", contranst);
        }

        public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
        {
            CommandBuffer cmd = CommandBufferPool.Get();
            //using的做法就是可以在FrameDebug上看到里面的所有渲染
            using (new ProfilingScope(cmd, m_ProfilingSampler))
            {
                //创建一张RT
                RenderTextureDescriptor opaqueDesc = renderingData.cameraData.cameraTargetDescriptor;
                opaqueDesc.depthBufferBits = 0;
                cmd.GetTemporaryRT(m_TemporaryColorTexture.id, opaqueDesc, filterMode);

                //将当前帧的颜色RT用自己的着色器渲处理然后输出到创建的贴图上
                Blit(cmd, m_Source, m_TemporaryColorTexture.Identifier(), m_Mat);

                //将处理后的RT重新渲染到当前帧的颜色RT上
                Blit(cmd, m_TemporaryColorTexture.Identifier(), m_Source);
            }
            //执行
            context.ExecuteCommandBuffer(cmd);

            //回收
            CommandBufferPool.Release(cmd);
        }
        public override void FrameCleanup(CommandBuffer cmd)
        {
            base.FrameCleanup(cmd);
            //销毁创建的RT
            cmd.ReleaseTemporaryRT(m_TemporaryColorTexture.id);
        }
    }



   //会显示在资产面板上
    public Color m_Color = Color.red;
    public float contranst;
    public float saturate;
    public float brightness;
    RendererPassTest m_Pass;

    //feature被创建时调用
    public override void Create()
    {
        m_Pass = new RendererPassTest();
    }

    //每一帧都会被调用
    public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
    {
        //将当前渲染的颜色RT传到Pass中
        m_Pass.Setup(renderer.cameraColorTarget, brightness, saturate,contranst);
        //将这个pass添加到渲染队列
        renderer.EnqueuePass(m_Pass);
    }

    //一帧渲染完最后调用
    protected override void Dispose(bool disposing)
    {
        base.Dispose(disposing);
    }
}



shader

Shader "Custom/PostEffect"
{
    Properties
    {
        [HideInInspector] _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _brightness ("Brightness", Range(0,1)) = 0.5
        _saturate ("Saturate", Range(0,1)) = 0.0
        _contranst ("Constrast", Range(-1,2)) = 0.0
    }
    SubShader
    {
        Tags 
        {
            "RenderPipeline"="UniversalRenderPipeline"
        }

        pass
        { 
            Cull Off
            ZWrite Off
            ZTest Always

            HLSLPROGRAM
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
            CBUFFER_START(UnityPerMaterial)
            float _brightness;
            float _saturate;
            float _contranst;
            CBUFFER_END
            TEXTURE2D(_MainTex);
            SAMPLER(sampler_MainTex);
            struct a2v{
                float4 positionOS:POSITION;
                float2 texcoord:TEXCOORD;
            };
            struct v2f
            {
                float4 positionCS:SV_POSITION;
                float2 texcoord:TEXCOORD;
            };
            #pragma vertex Vert
            #pragma fragment Frag
            v2f Vert(a2v i)
            {
                v2f o;
                o.positionCS =TransformObjectToHClip(i.positionOS.xyz);
                o.texcoord = i.texcoord;
                return o;
            }
            float4 Frag(v2f i) :SV_TARGET
            {
                float4 tex = SAMPLE_TEXTURE2D(_MainTex,sampler_MainTex,i.texcoord);
                float gray = 0.21*tex.x + 0.72 * tex.y + 0.072*tex.z;
                tex.xyz *= _brightness;
                tex.xyz = lerp (float3(gray,gray,gray), tex.xyz, _saturate);
                tex.xyz = lerp (float3(0.5,0.5,0.5), tex.xyz, _contranst);
                return tex;
            }
            ENDHLSL
        }
    }
    
}   

---------------------博主:mx

你可能感兴趣的:(Shader学习笔记,unity,shader,渲染管线,3d渲染,hlsl)