美文网首页好文章
URP屏幕后处理

URP屏幕后处理

作者: BacteriumFox | 来源:发表于2021-01-10 12:31 被阅读0次

    URP屏幕后处理

    由于Unity对URP的屏幕后处理需集成要到2019.4版本后才稳定,所以升级Unity版本到2019.4.9

    Post Processing

    在创建我们自己屏幕后处理系统前,我们需要先学会使用UnityURP管线中集成的屏后处理系统。

    低于Unity2019.4版本的URP是没有Volume组件的

    1. 我们可以将Volume组件添加到GameObject,或者在Hierarchy面板中中右键单击并在Volume标题下选择某些内容。

      • Global Volume代表后处理效果应用所有摄像机
      • Box Volume会在场景中创建一个盒子区域(该区域在Scene中用BoxCollider组件显示轮廓),只有摄像机进入该区域才会应用后处理效果
      • Sphere Volume是一个球形区域,效果同上
      • Convex Mesh Volume允许我们使用自定义的网格区域
    2. Volume组件上有如下参数

      属性 描述
      Mode Global:使Volume无边界并影响场景中的每一个摄像机。 Local:为Volume指定边界,Volume只影响在边界内部的射线机。
      Blend Distance URP从Volume Collider开始融合的最远距离。0表示URP立即应用Volume的Override;该属性只有在非Global Volume下才出现
      Weight Volume在场景中的影响值
      Priority 当Volume在场景中有多个Volume时,URP通过此值决定使用哪一个Volume。URP优先使用priority更高的
      Profile Profile Asset存储URP处理Volume的数据
    3. 点击Profile旁的New按钮,新建一个后处理配置文件,然后我们就可以通过Add Override添加各种URP内置后处理效果了。

      有关URP后处理效果清单见https://docs.unity3d.com/Packages/com.unity.render-pipelines.universal@8.0/manual/EffectList.html

    4. 当我们为配置文件添加色差效果Chromatic Aberration,并开启效果后会发现,在Scene视图中已经出现了效果,但在Game视图中却没有任何变化。

      接下来我们需要将场景中的摄像机开启屏幕后处理,选中场景中摄像机,在Inspector面板中找到Rendering栏下的Post Processing开关,勾选上。

      现在Game中已经出现效果

    这里列出URP中可用的后处理效果

    • 高光(Bloom)高光效果从图片中的光亮部分的边缘长生羽毛形状的光。并且产生遮挡。Bloom中有一个Lens Dirt特征,这个可以用于产生全屏光斑。
    • 通道混合器(Channel Mixer):通道混合器提供每个颜色通道的信息,通过调整不同通道的影响可以实现不同的屏幕效果。
    • 色差(Chromatic Aberration):仿真实现了真实摄像机无法将所有颜色融合到一个点。
    • 颜色调整(Color Adjustments) 调整整体的色调、亮度和对比度
    • 颜色曲线(Color Curves):通过曲线的方式调整色相、饱和度或者亮度。
    • 景深(Depth Of Field): 景深组件模拟相机镜头的聚焦特性。现实生活中,相机只能对特定距离清晰对焦。距离摄像机较远和较近的物体无法聚焦。根据模糊效果引入了Bokeh(散景),Bokeh指当图像失焦时出现在明亮区域的视觉伪像。
    • 胶片颗粒(Film Grain):Film Grain是加工摄影胶片的随机光学纹理,因为存在卤化银产生的金属银或染料云的小颗粒,其已经接收到了足够的光子。
    • 镜头变形(Lens Distortion):扭曲图片模拟真实的镜头
    • 提升伽马增益(Lift Gamma Gain):调整图像的lift、Gamma、Gain
    • 运动模糊(Motion Blur):模拟真实摄像机在拍摄运动物体时,运动速度大于曝光时间的时候出现的模糊效果。
    • 帕尼尼投影(Panini Projection):一种圆柱形投影,保持垂直方向上的垂直,在渲染大视角的时候提供更好的效果。视角120度无后处理。
    • 阴影 中间色调 高光(Shadows Midtones Hightlights):使用圆环工具进行三个熟知的调整
    • 分割色调(Split Toning):根据亮度值对不同的区域进行着色,帮助我们实现更加独特的视觉效果。可以通过此效果实现阴影和高光部分不同的色调。
    • 色调映射(Tonemapping):在屏幕上重新映射HDR的过程
    • 玩具相机(Vignette):暗角效果和去饱和,现实中造成这种结果的原因通常是堆叠滤镜,辅助镜片和不当的遮光罩。
    • 白平衡(White Balance):应用白平衡组件,消除不真实的偏色,从而使白色在图像中呈现白色。我们也可以用来呈现冷色或者暖色的渲染效果。

    扩展Volume

    既然我们已经学会了如何使用Volume组件,那么我们接下来所需做的就是如何去扩展该组件,增加我们的屏幕后处理效果。

    解读Volume运作

    首先我们可以在URP包目录下的com.unity.render-pipelines.universal@7.5.1\Runtime\Overrides文件夹中找到,包含了所有为Volume配置文件添加的效果的属性脚本。为方便做比较,我们打开目录中的Bloom脚本,可以发现脚本中只有属性,且这些属性名对应了Volume组件中的效果属性。

    然后我们可以找到一个文件com.unity.render-pipelines.universal@7.5.1\Runtime\Passes\PostProcessPass.cs,这个PostProcessPass就是URP内置后处理的核心,它继承了ScriptableRenderPass,方便在URP管线下扩展额外的Pass通道。

    所有继承ScriptableRenderPass组件的子类需要实现一个方法:

    public abstract void Execute(ScriptableRenderContext context, ref RenderingData renderingData);
    

    其实该方法的作用和我们在Built-in管线下写后处理框架时用到的oid OnRenderImage(RenderTexture src, RenderTexture dest)方法功能是一样的,在每帧渲染,渲染管线都会调用该方法。然后我们会在该方法里通过Shader的Pass进行后处理。

    其中的ScriptableRenderContext 参数我们在前面SRP尝试章节里已经见识过,它是定义自定义渲染管道使用的状态和绘制命令,使用该参数我们可以进行额外的Pass绘制。RenderingData也好理解,就是当前调用该方法的绘制信息,其中包含调用该次绘制的相机信息、光源信息、阴影信息等;注意,该参数带有ref关键字,说明我们是可以直接对这些绘制信息进行修改,并影响后续管线的成像的。

    可编程渲染功能

    从前面URP源代码可以看出,其实URP的后处理方式和Built-in管线下的后处理方式思路相同,都是通过C#代码去调用Shader进行后处理。但有一点不同,在Built-in管线下,后处理脚本我们是继承Mono的,直接将脚本挂在对象上就可运作(mono自动调用OnRenderImage方法);但是URP下继承的是ScriptableRenderPass,该类是一个对象,我们由如何让他运作呢。

    在我们URP管线的Inspector面板下,RendererList中有我们当前真正使用的渲染器列表,

    跳转到使用渲染器的Inspector面板后我们可以看到Post ProcessData,Post ProcessData正是URP用于引用各种后处理Shader的对象。

    而下方的Rederer Features则是我们的重点,它允许我们添加额外的渲染功能,也就是我们可以写一个功能脚本,在脚本中创建我们自定义的ScriptableRenderPass对象,然后添加到该列表中,后续URP管线在渲染过程中会自动调用该功能,也就是间接调用我们自定义的后处理对象,以此实现URP管线下的自定义后处理。

    想要编写额外的渲染功能,我们需要将脚本继承ScriptableRendererFeature,并且实现AddRenderPassesCreate函数。Create方法会在该功能初始化时调用,我们可以在方法中创建我们的后处理对象。AddRenderPasses将会在相机被设置渲染器时调用。

    调整屏幕亮度、饱和度、对比度

    既然运作方式解析了,那么进入实操环节。

    创建Shader

    创建Shader-Brightness Saturation And Contrast,该Shader比较简单,没有什么新的语法。

    在不知道该Shader是否正确的情况下,可以创建一个Plane拖入到摄像机视野内(这很重要),再创建该Shader的材质,将材质赋给Palne。最后再给材质添加纹理,调整不同的参数,在Game中看效果是否正确。

    Shader "URP/Brightness Saturation And Contrast"
    {
        Properties
        {
            // 基础纹理
            _MainTex ("Base (RGB)", 2D) = "white" { }
            // 亮度
            _Brightness ("Brightness", Float) = 1
            // 饱和度
            _Saturation ("Saturation", Float) = 1
            // 对比度
            _Contrast ("Contrast", Float) = 1
        }
        SubShader
        {
            Tags { "RenderPipeline" = "UniversalPipeline" }
            
            HLSLINCLUDE
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
            
            CBUFFER_START(UnityPerMaterial)
            float4 _MainTex_ST;
            half _Brightness;
            half _Saturation;
            half _Contrast;
            CBUFFER_END
            
            ENDHLSL
            
            Pass
            {
                // 开启深度测试 关闭剔除 关闭深度写入
                ZTest Always Cull Off ZWrite Off
                
                HLSLPROGRAM
                
                #pragma vertex vert
                #pragma fragment frag
                
                #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
                
                // 声明纹理
                TEXTURE2D(_MainTex);
                // 声明采样器
                SAMPLER(sampler_MainTex);
                
                struct a2v
                {
                    float4 vertex: POSITION;
                    
                    float4 texcoord: TEXCOORD0;
                };
                
                struct v2f
                {
                    float4 pos: SV_POSITION;
                    half2 uv: TEXCOORD0;
                };
                
                v2f vert(a2v v)
                {
                    v2f o;
                    
                    o.pos = TransformObjectToHClip(v.vertex.xyz);
                    
                    o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
                    
                    return o;
                }
                
                half4 frag(v2f i): SV_Target
                {
                    // 纹理采样
                    half4 renderTex = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv);
                    
                    // 调整亮度 = 原颜色 * 亮度值
                    half3 finalColor = renderTex.rgb * _Brightness;
                    
                    // 调整饱和度
                    // 亮度值(饱和度为0的颜色) = 每个颜色分量 * 特定系数
                    half luminance = 0.2125 * renderTex.r + 0.7154 * renderTex.g + 0.0721 * renderTex.b;
                    half3 luminanceColor = half3(luminance, luminance, luminance);
                    // 插值亮度值和原图
                    finalColor = lerp(luminanceColor, finalColor, _Saturation);
                    
                    // 调整对比度
                    // 对比度为0的颜色
                    half3 avgColor = half3(0.5, 0.5, 0.5);
                    finalColor = lerp(avgColor, finalColor, _Contrast);
                    
                    return half4(finalColor, renderTex.a);
                }            
                ENDHLSL            
            }
        }
        
        Fallback Off
    }
    

    创建属性参数脚本

    1. 编写类BrightnessSaturationContrast继承VolumeComponent组件和IPostProcessComponent接口,用以继承Volume框架。

    2. 在方法中我们根据材质所需的三个参数亮度、饱和度、对比度创建三个属性。

              public ClampedFloatParameter brightness = new ClampedFloatParameter(0f, 0, 3);
              public ClampedFloatParameter saturation = new ClampedFloatParameter(0f, 0, 3);
              public ClampedFloatParameter contrast = new ClampedFloatParameter(0f, 0, 3);
      

    创建可编程渲染Pass脚本

    1. 创建C#脚本AdditionPostProcessPass,继承自ScriptableRenderPass,并实现Execute方法。

    2. 创建所需属性

              //标签名,用于续帧调试器中显示缓冲区名称
              const string CommandBufferTag = "AdditionalPostProcessing Pass";
          
              // 用于后处理的材质
              public Material m_Material;
      
              // 属性参数组件
              BrightnessSaturationContrast m_BrightnessSaturationContrast;
      
              // 颜色渲染标识符
              RenderTargetIdentifier m_ColorAttachment;
              // 临时的渲染目标
              RenderTargetHandle m_TemporaryColorTexture01;
      
    3. 创一个入口函数,用于后续渲染管线功能脚本写入参数

              // 设置渲染参数
              public void Setup(RenderTargetIdentifier _ColorAttachment, Material Material)
              {
                  this.m_ColorAttachment = _ColorAttachment;
      
                  m_Material = Material;
              } 
      
    4. 修改Execute方法,在方法中我们通过VolumeManager.instance.stack单例获取Volume框架中所有的堆栈,在从堆栈中获取我们上一部创建的属性参数组件,由于Execute是每帧调用,所有该组件也是实时更新的。

      然后我们使用标签名获取一个命令缓冲区,将该命令缓冲区与Execute的参数RenderingData渲染信息一起交给Render方法进行后处理。

      在后处理完成后我们调用context.ExecuteCommandBuffer(cmd);方法执行该命令缓冲区,最后释放内存。

              public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
              {
                  // 从Volume框架中获取所有堆栈
                  var stack = VolumeManager.instance.stack;
                  // 从堆栈中查找对应的属性参数组件
                  m_BrightnessSaturationContrast = stack.GetComponent<BrightnessSaturationContrast>();
      
                  // 从命令缓冲区池中获取一个带标签的命令缓冲区,该标签名可以在后续帧调试器中见到
                  var cmd = CommandBufferPool.Get(CommandBufferTag);
      
                  // 调用渲染函数
                  Render(cmd, ref renderingData);
      
                  // 执行命令缓冲区
                  context.ExecuteCommandBuffer(cmd);
                  // 释放命令缓存
                  CommandBufferPool.Release(cmd);
                  // 释放临时RT
                  cmd.ReleaseTemporaryRT(m_TemporaryColorTexture01.id);
              }
      
    5. 接下来我们编写渲染方法Render,在Render方法中我们获取属性参数组件中的参数,赋值给材质。

      然后通过RenderingData对象中的相机信息创建一个临时缓冲区,然后将颜色渲染器中的颜色通过Shader进行计算后保存到临时缓冲区中。

      最后在从临时缓冲区中读取出来返还到主纹理中。

           // 渲染
           void Render(CommandBuffer cmd, ref RenderingData renderingData)
           {       
               // VolumeComponent是否开启,且非Scene视图摄像机
               if (m_BrightnessSaturationContrast.IsActive() && !renderingData.cameraData.isSceneViewCamera)
               {
                   // 写入参数
                   m_Material.SetFloat("_Brightness", m_BrightnessSaturationContrast.brightness.value);
                   m_Material.SetFloat("_Saturation", m_BrightnessSaturationContrast.saturation.value);
                   m_Material.SetFloat("_Contrast", m_BrightnessSaturationContrast.contrast.value);
      
                   // 获取目标相机的描述信息
                   RenderTextureDescriptor opaqueDesc = renderingData.cameraData.cameraTargetDescriptor;
                   // 设置深度缓冲区
                   opaqueDesc.depthBufferBits = 0;
                   // 通过目标相机的渲染信息创建临时缓冲区
                   cmd.GetTemporaryRT(m_TemporaryColorTexture01.id, opaqueDesc);
      
                   // 通过材质,将计算结果存入临时缓冲区
                   cmd.Blit(m_ColorAttachment, m_TemporaryColorTexture01.Identifier(), m_Material);
                   // 再从临时缓冲区存入主纹理
                   cmd.Blit(m_TemporaryColorTexture01.Identifier(), m_ColorAttachment);
               }
      

    创建可编程渲染功能脚本

    1. 创建类AdditionPostProcessRendererFeature,继承ScriptableRendererFeature抽象类,并实现AddRenderPassesCreate方法

    2. 设置三个参数,公开属性Shader、私有属性AdditionPostProcessPass对象和材质

              // 用于后处理的Shader 
              public Shader shader;
              // 后处理Pass
              AdditionPostProcessPass postPass;
              // 根据Shader生成的材质
              Material _Material=null;
      
    3. 修改Create方法,在方法中创建AdditionPostProcessPass对象,并修改该类的渲染时机,在透明物体渲染后。

    4. 修改AddRenderPasses方法,在方法中通过Shader创建材质,然后从ScriptableRenderer参数中获取主纹理;接下来将纹理和材质传入AdditionPostProcessPass对象中,最后将该对象添加到渲染管线队列中。

              public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
              {
                  // 检测Shader是否存在
                  if (shader == null)
                      return;
      
                  // 创建材质
                  if (_Material==null)
                      _Material = CoreUtils.CreateEngineMaterial(shader);
      
                  // 获取当前渲染相机的目标颜色,也就是主纹理
                  var cameraColorTarget = renderer.cameraColorTarget;     
      
                  // 设置调用后处理Pass
                  postPass.Setup(cameraColorTarget, _Material);
                  
                  // 添加该Pass到渲染管线中
                  renderer.EnqueuePass(postPass);
              }
      

    配置管线

    1. 配置Volume组件,将BrightnessSaturationContrast属性参数组件添加到效果列表中

    2. 配置管线,在URP管线的配置文件中添加我们编写的渲染功能AdditionPostProcessRendererFeature

    3. 赋值Shader

    4. 修改属性参数组件的参数,以降低饱和度

    完整代码

    Shader——Brightness Saturation And Contrast

    Shader "URP/Brightness Saturation And Contrast"
    {
        Properties
        {
            // 基础纹理
            _MainTex ("Base (RGB)", 2D) = "white" { }
            // 亮度
            _Brightness ("Brightness", Float) = 1
            // 饱和度
            _Saturation ("Saturation", Float) = 1
            // 对比度
            _Contrast ("Contrast", Float) = 1
        }
        SubShader
        {
            Tags { "RenderPipeline" = "UniversalPipeline" }
            
            HLSLINCLUDE
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
            
            CBUFFER_START(UnityPerMaterial)
            float4 _MainTex_ST;
            half _Brightness;
            half _Saturation;
            half _Contrast;
            CBUFFER_END
            
            ENDHLSL
            
            Pass
            {
                // 开启深度测试 关闭剔除 关闭深度写入
                ZTest Always Cull Off ZWrite Off
                
                HLSLPROGRAM
                
                #pragma vertex vert
                #pragma fragment frag
                
                #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
                
                // 声明纹理
                TEXTURE2D(_MainTex);
                // 声明采样器
                SAMPLER(sampler_MainTex);
                
                struct a2v
                {
                    float4 vertex: POSITION;
                    
                    float4 texcoord: TEXCOORD0;
                };
                
                struct v2f
                {
                    float4 pos: SV_POSITION;
                    half2 uv: TEXCOORD0;
                };
                
                v2f vert(a2v v)
                {
                    v2f o;
                    
                    o.pos = TransformObjectToHClip(v.vertex.xyz);
                    
                    o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
                    
                    return o;
                }
                
                half4 frag(v2f i): SV_Target
                {
                    // 纹理采样
                    half4 renderTex = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv);
                    
                    // 调整亮度 = 原颜色 * 亮度值
                    half3 finalColor = renderTex.rgb * _Brightness;
                    
                    // 调整饱和度
                    // 亮度值(饱和度为0的颜色) = 每个颜色分量 * 特定系数
                    half luminance = 0.2125 * renderTex.r + 0.7154 * renderTex.g + 0.0721 * renderTex.b;
                    half3 luminanceColor = half3(luminance, luminance, luminance);
                    // 插值亮度值和原图
                    finalColor = lerp(luminanceColor, finalColor, _Saturation);
                    
                    // 调整对比度
                    // 对比度为0的颜色
                    half3 avgColor = half3(0.5, 0.5, 0.5);
                    finalColor = lerp(avgColor, finalColor, _Contrast);
                    
                    return half4(finalColor, renderTex.a);
                }            
                ENDHLSL            
            }
        }
        
        Fallback Off
    }
    

    BrightnessSaturationContrast

    using System;
    
    // 通用渲染管线程序集
    namespace UnityEngine.Rendering.Universal
    {
        // 实例化类     添加到Volume组件菜单中
        [Serializable, VolumeComponentMenu("Addition-Post-processing/BrightnessSaturationContrast")]
        // 继承VolumeComponent组件和IPostProcessComponent接口,用以继承Volume框架
        public class BrightnessSaturationContrast : VolumeComponent, IPostProcessComponent
        {
            // 在框架下的属性与Unity常规属性不一样,例如 Int 由 ClampedIntParameter 取代。
            public ClampedFloatParameter brightness = new ClampedFloatParameter(0f, 0, 3);
            public ClampedFloatParameter saturation = new ClampedFloatParameter(0f, 0, 3);
            public ClampedFloatParameter contrast = new ClampedFloatParameter(0f, 0, 3);
            // 实现接口
            public bool IsActive()
            {
                return active;
            }
    
            public bool IsTileCompatible()
            {
                return false;
            }
        }
    }
    

    AdditionPostProcessPass

    namespace UnityEngine.Rendering.Universal
    {
        /// <summary>
        /// 附加的后处理Pass
        /// </summary>
        public class AdditionPostProcessPass : ScriptableRenderPass
        {
            //标签名,用于续帧调试器中显示缓冲区名称
            const string CommandBufferTag = "AdditionalPostProcessing Pass";
        
            // 用于后处理的材质
            public Material m_Material;
    
            // 属性参数组件
            BrightnessSaturationContrast m_BrightnessSaturationContrast;
    
            // 颜色渲染标识符
            RenderTargetIdentifier m_ColorAttachment;
            // 临时的渲染目标
            RenderTargetHandle m_TemporaryColorTexture01;
    
            public AdditionPostProcessPass()
            {          
                m_TemporaryColorTexture01.Init("_TemporaryColorTexture1");
            }
    
            // 设置渲染参数
            public void Setup(RenderTargetIdentifier _ColorAttachment, Material Material)
            {
                this.m_ColorAttachment = _ColorAttachment;
    
                m_Material = Material;
            }     
    
            /// <summary>
            /// URP会自动调用该执行方法
            /// </summary>
            /// <param name="context"></param>
            /// <param name="renderingData"></param>
            public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
            {
                // 从Volume框架中获取所有堆栈
                var stack = VolumeManager.instance.stack;
                // 从堆栈中查找对应的属性参数组件
                m_BrightnessSaturationContrast = stack.GetComponent<BrightnessSaturationContrast>();
    
                // 从命令缓冲区池中获取一个带标签的渲染命令,该标签名可以在后续帧调试器中见到
                var cmd = CommandBufferPool.Get(CommandBufferTag);
    
                // 调用渲染函数
                Render(cmd, ref renderingData);
    
                // 执行命令缓冲区
                context.ExecuteCommandBuffer(cmd);
                // 释放命令缓存
                CommandBufferPool.Release(cmd);
                // 释放临时RT
                cmd.ReleaseTemporaryRT(m_TemporaryColorTexture01.id);
            }
    
            // 渲染
            void Render(CommandBuffer cmd, ref RenderingData renderingData)
            {       
                // VolumeComponent是否开启,且非Scene视图摄像机
                if (m_BrightnessSaturationContrast.IsActive() && !renderingData.cameraData.isSceneViewCamera)
                {
                    // 写入参数
                    m_Material.SetFloat("_Brightness", m_BrightnessSaturationContrast.brightness.value);
                    m_Material.SetFloat("_Saturation", m_BrightnessSaturationContrast.saturation.value);
                    m_Material.SetFloat("_Contrast", m_BrightnessSaturationContrast.contrast.value);
    
                    // 获取目标相机的描述信息
                    RenderTextureDescriptor opaqueDesc = renderingData.cameraData.cameraTargetDescriptor;
                    // 设置深度缓冲区
                    opaqueDesc.depthBufferBits = 0;
                    // 通过目标相机的渲染信息创建临时缓冲区
                    cmd.GetTemporaryRT(m_TemporaryColorTexture01.id, opaqueDesc);
    
                    // 通过材质,将计算结果存入临时缓冲区
                    cmd.Blit(m_ColorAttachment, m_TemporaryColorTexture01.Identifier(), m_Material);
                    // 再从临时缓冲区存入主纹理
                    cmd.Blit(m_TemporaryColorTexture01.Identifier(), m_ColorAttachment);
                }
            }       
        }
    }
    

    AdditionPostProcessRendererFeature

    namespace UnityEngine.Rendering.Universal
    {
        /// <summary>
        /// 可编程渲染功能
        /// 必须要继承ScriptableRendererFeature抽象类,
        /// 并且实现AddRenderPasses跟Create函数
        /// </summary>
        public class AdditionPostProcessRendererFeature : ScriptableRendererFeature
        {
            // 用于后处理的Shader 
            public Shader shader;
            // 后处理Pass
            AdditionPostProcessPass postPass;
            // 根据Shader生成的材质
            Material _Material=null;
    
            //在这里,您可以在渲染器中注入一个或多个渲染通道。
            //每个摄像机设置一次渲染器时,将调用此方法。
            public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
            {
                // 检测Shader是否存在
                if (shader == null)
                    return;
    
                // 创建材质
                if (_Material==null)
                    _Material = CoreUtils.CreateEngineMaterial(shader);
    
                // 获取当前渲染相机的目标颜色,也就是主纹理
                var cameraColorTarget = renderer.cameraColorTarget;     
    
                // 设置调用后处理Pass
                postPass.Setup(cameraColorTarget, _Material);
                
                // 添加该Pass到渲染管线中
                renderer.EnqueuePass(postPass);
            }
    
           
            // 对象初始化时会调用该函数
            public override void Create()
            {
                postPass = new AdditionPostProcessPass();
                // 渲染时机 = 透明物体渲染后
                postPass.renderPassEvent = RenderPassEvent.AfterRenderingTransparents; 
            }
        }
    }
    

    相关文章

      网友评论

        本文标题:URP屏幕后处理

        本文链接:https://www.haomeiwen.com/subject/yupkaktx.html