• 【Unity】RenderFeature笔记


    【Unity】RenderFeature笔记

    RenderFeature是在urp中添加的额外渲染pass,并可以将这个pass插入到渲染列队中的任意位置。内置渲染管线中Graphics 的功能需要在RenderFeature里实现,常见的如DrawMesh和Blit

    ​ 可以实现的效果包括但不限于

    1. 后处理,可以编写shader对整个渲染画面进行修改。比如一些全局特效包括:场景描边,地形扫描;

    2. 创建网格,通过DrawMesh绘制定义的网格;

    3. 渲染画面,将场景渲染到纹理;

    一、RanderFeature简介

    1. 创建RanderFeature

    在project中Create→Rendering→URPRenderFeature

    2.RanderFeature结构
    using UnityEngine.Rendering;
    using UnityEngine.Rendering.Universal;
    
    public class CustomRenderPassFeatureTest : ScriptableRendererFeature
    {
        class CustomRenderPass : ScriptableRenderPass
        {
            // 在执行渲染通道之前调用
            // 创建临时渲染目标纹理。
            //为Execute提前准备需要的RenderTexture或者其它变量
            public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData){}
            //核心方法,实现这个renderPass的逻辑
            public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData){}
            //释放在OnCameraSetup里,声明的变量如TemporaryRenderTexture
            public override void OnCameraCleanup(CommandBuffer cmd) {}
        }
        CustomRenderPass m_ScriptablePass;
    
        /// 
        public override void Create()
        {
            m_ScriptablePass = new CustomRenderPass();
            //定义渲染的位置
            m_ScriptablePass.renderPassEvent = RenderPassEvent.AfterRenderingOpaques;
        }
    
        // 这里你可以在渲染器中注入一个或多个渲染通道。
        //每一帧都执行
        public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
        {
            //把实例化的CustomRenderPass插入渲染管线
            renderer.EnqueuePass(m_ScriptablePass);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    3.RenderFeatrue使用

    在Universal Render Pipeline Asset_Renderer直接Add RenderFeatrue

    二、后处理效果

    关键词
    1、CommandBuffer.Blit

    Blit是很常用的后期效果方法,在Build_in中常常是在OnRenderImage里被调用,与urp不同的是,在build_in里是通过Graphics.Blit调用。

    Graphics.Blit

    常用的接口: Blit(RenderTexturesource, RenderTexture dest, Material mat);

    即使用着色器将源纹理复制到目标渲染纹理。

    CommandBuffer.Blit

    常用的接口:public void Blit (Rendering.RenderTargetIdentifier source, Rendering.RenderTargetIdentifier dest, Material mat);

    这与 Graphics.Blit相似 - 主要用于从一个(渲染)纹理复制到其他纹理,可能使用自定义着色器;

    源纹理或渲染目标将作为“_MainTex”属性传递给材质。

    在shader中,_MainTex对应的是source,最后retrun对应的是dest

    2、RenderTargetIdentifier

    渲染目标标识符,标识 CommandBuffer的 RenderTexture;

    使用 CommandBuffer.GetTemporaryRT 创建的具有名称的临时渲染纹理;

    ScriptableRenderPass中有colorAttachment和depthAttachment是可以直接使用;

    RenderTargetHandle.CameraTarget.Identifier()可以得到当前的渲染标识符

    renderingData.cameraData.renderer.cameraColorTarget 也可以得到当前的渲染标识符

    简单实现

    实现脚本

    using UnityEngine;
    using UnityEngine.Rendering;
    using UnityEngine.Rendering.Universal;
    
    public class CustomRenderPassFeatureTest : ScriptableRendererFeature
    {
        //结构说明
        class CustomRenderPass : ScriptableRenderPass
        {
            // 在执行渲染通道之前调用
            // 创建临时渲染目标纹理。
            //为Execute提前准备需要的RenderTexture或者其它变量
    
            public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData) {}
          
            //核心方法,实现这个renderPass的逻辑
            public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData){}
    
            //释放在OnCameraSetup里,声明的变量如TemporaryRenderTexture
            public override void OnCameraCleanup(CommandBuffer cmd){}
        }
        //后处理效果
        class CustomRenderShaderPostPass : ScriptableRenderPass
        {  
            //定义渲染材质,通过Create方法赋值
            public Material _Material;
            public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
            {
                //创建一个CommandBuffer
                CommandBuffer cmd = CommandBufferPool.Get("ShowShader");
                //这里有一个疑问,渲染标识符不管怎么传都不影响结果
                cmd.Blit(colorAttachment, RenderTargetHandle.CameraTarget.Identifier(), _Material);
                //执行CommandBuffer
                context.ExecuteCommandBuffer(cmd);
                //回收CommandBuffer
                CommandBufferPool.Release(cmd);
            }
        }
    
        CustomRenderShaderPostPass m_ScriptablePassPost;
        public Shader shader;
        /// 
        public override void Create()
        {
            m_ScriptablePassPost = new CustomRenderShaderPostPass();
            //通过创建一个渲染材质
            m_ScriptablePassPost._Material = new Material(shader);
            //定义渲染的位置
            m_ScriptablePassPost.renderPassEvent = RenderPassEvent.AfterRenderingOpaques;
        }
        // 这里你可以在渲染器中注入一个或多个渲染通道。
        //每一帧都执行
        public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
        {
            //把实例化的CustomRenderPass插入渲染管线
            renderer.EnqueuePass(m_ScriptablePassPost);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    1.实现饱和度和对比度调整

    用shaderGraph实现

    用shader实现

    Shader "Unlit/SaturationContrastShader"
    {
        SubShader
        {
            Pass
            {
               ZTest Always ZWrite Off
                CGPROGRAM
    
                #pragma vertex vert_img  // 使用内置的vert_img顶点着色器
                #pragma fragment frag
    
                #include "UnityCG.cginc"
    
                sampler2D _CameraColorTexture; 
                //饱和度
                fixed3   Saturation_float(float3 In, float Saturation)
                {
                    float luma = dot(In, float3(0.2126729, 0.7151522, 0.0721750));
                    return luma.xxx + Saturation.xxx * (In - luma.xxx);
                }
                //对比度
                fixed3  Contrast_float(float3 In, float Contrast)
                {
                    float midpoint = pow(0.5, 2.2);
                    return (In - midpoint) * Contrast + midpoint;
                }
    
                fixed4 frag (v2f_img i) : SV_Target
                {
                    fixed4 col = tex2D(_CameraColorTexture, i.uv);
                    fixed3  Saturation =  Saturation_float(col, 5);
                    fixed3  Contrast = Saturation_float(Saturation, 5);
                    return fixed4(Contrast.x, Contrast.y, Contrast.z,0.1);
                }
                ENDCG
            }
        }
       FallBack Off
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    使用前

    使用后

    三、创建网格

    关键词
    1、CommandBuffer.DrawMesh

    常用的接口:DrawMesh(Mesh mesh, Matrix4x4 matrix, Material material);

    这个接口相对简单,传入mesh,变换矩阵,和材质

    简单实现

    这里接着上一个CustomRenderPassFeatureTest写,同时实现后处理和网格创建

    
    using UnityEngine;
    using UnityEngine.Rendering;
    using UnityEngine.Rendering.Universal;
    
    public class CustomRenderPassFeatureTest : ScriptableRendererFeature
    {
        //结构说明
        class CustomRenderPass : ScriptableRenderPass
        {
            // 在执行渲染通道之前调用
            // 创建临时渲染目标纹理。
            //为Execute提前准备需要的RenderTexture或者其它变量
    
            public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData) {}
          
            //核心方法,实现这个renderPass的逻辑
            public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData){}
    
            //释放在OnCameraSetup里,声明的变量如TemporaryRenderTexture
            public override void OnCameraCleanup(CommandBuffer cmd){}
        }
        //后处理效果
        class CustomRenderShaderPostPass : ScriptableRenderPass
        {  
            //定义渲染材质,通过Create方法赋值
            public Material _Material;
            public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
            {
                //创建一个CommandBuffer
                CommandBuffer cmd = CommandBufferPool.Get("ShowShader");
                //这里有一个疑问,渲染标识符不管怎么传都不影响结果
                cmd.Blit(colorAttachment, RenderTargetHandle.CameraTarget.Identifier(), _Material);
                //执行CommandBuffer
                context.ExecuteCommandBuffer(cmd);
                //回收CommandBuffer
                CommandBufferPool.Release(cmd);
            }
        }
        //绘制网格
        class CustomRenderPassCreateMesh : ScriptableRenderPass
        {
            public Material _Material;
            public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
            {
                CommandBuffer cmd = CommandBufferPool.Get("CreateMesh");
                cmd.DrawMesh(CreateMesh(), Matrix4x4.identity, _Material);
                //这里和后处理一样的操作
                context.ExecuteCommandBuffer(cmd);
                CommandBufferPool.Release(cmd);
            }
            //创建网格
            Mesh CreateMesh()
            {
                Mesh mesh = new Mesh();
                mesh.vertices = new Vector3[4] { new Vector3(1, 1, 1), new Vector3(-1, 1, 1), new Vector3(-1, 1, -1), new Vector3(1, 1, -1) };
                int[] indices = new int[8] { 0, 1, 1, 2, 2, 3, 3, 0 };
                //创建简单的线网格
                mesh.SetIndices(indices, MeshTopology.Lines, 0);
                return mesh;
            }
        }
    
        CustomRenderShaderPostPass m_ScriptablePassPost;
        CustomRenderPassCreateMesh m_ScriptablePassCreateMesh;
        public Shader shaderPost;
        public Shader shaderMesh;
        /// 
        public override void Create()
        {
            m_ScriptablePassPost = new CustomRenderShaderPostPass();
            //通过创建一个渲染材质
            m_ScriptablePassPost._Material = new Material(shaderPost);
            //定义渲染的位置
            m_ScriptablePassPost.renderPassEvent = RenderPassEvent.AfterRendering;
    
            m_ScriptablePassCreateMesh = new CustomRenderPassCreateMesh();
            m_ScriptablePassCreateMesh._Material = new Material(shaderMesh);
            m_ScriptablePassCreateMesh.renderPassEvent = RenderPassEvent.AfterRenderingOpaques;
        }
    
        // 这里你可以在渲染器中注入一个或多个渲染通道。
        //每一帧都执行
        public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
        {
            //把实例化的CustomRenderPass插入渲染管线
            renderer.EnqueuePass(m_ScriptablePassPost);
            renderer.EnqueuePass(m_ScriptablePassCreateMesh);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90

    实现效果

    知识点:RenderPassEvent控制渲染的顺序,上图我们可以看到,创建的线是可以被模型遮挡和遮挡模型的。但是如果把m_ScriptablePassCreateMesh.renderPassEvent=RenderPassEvent.AfterRendering 就会发现线完全遮挡模型,即线最后渲染

    四、渲染画面到图片

    关键词
    1、GetTemporaryRT

    获取临时渲染纹理

    可使用给定参数创建临时渲染纹理,并使用 nameID 将其设置为全局着色器属性。使用 Shader.PropertyToID创建整数名称。

    2、Shader.PropertyToID

    获取着色器属性名称的唯一标识符。

    static string RtName = "_TestRT";
    static int RT_ID = Shader.PropertyToID(RtName);
    
    • 1
    • 2

    简单实现

    同样接着上一个CustomRenderPassFeatureTest写,同时实现后处理和网格创建

    
    using UnityEngine;
    using UnityEngine.Rendering;
    using UnityEngine.Rendering.Universal;
    
    public class CustomRenderPassFeatureTest : ScriptableRendererFeature
    {
        //结构说明
        class CustomRenderPass : ScriptableRenderPass
        {
            // 在执行渲染通道之前调用
            // 创建临时渲染目标纹理。
            //为Execute提前准备需要的RenderTexture或者其它变量
    
            public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData) {}
          
            //核心方法,实现这个renderPass的逻辑
            public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData){}
    
            //释放在OnCameraSetup里,声明的变量如TemporaryRenderTexture
            public override void OnCameraCleanup(CommandBuffer cmd){}
        }
        //后处理效果
        class CustomRenderShaderPostPass : ScriptableRenderPass
        {  
            //定义渲染材质,通过Create方法赋值
            public Material _Material;
            public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
            {
                //创建一个CommandBuffer
                CommandBuffer cmd = CommandBufferPool.Get("ShowShader");
                //这里有一个疑问,渲染标识符不管怎么传都不影响结果
                cmd.Blit(colorAttachment, RenderTargetHandle.CameraTarget.Identifier(), _Material);
                //执行CommandBuffer
                context.ExecuteCommandBuffer(cmd);
                //回收CommandBuffer
                CommandBufferPool.Release(cmd);
            }
        }
        //创建网格
        class CustomRenderPassCreateMesh : ScriptableRenderPass
        {
            public Material _Material;
            public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
            {
                CommandBuffer cmd = CommandBufferPool.Get("CreateMesh");
                cmd.DrawMesh(CreateMesh(), Matrix4x4.identity, _Material);
                context.ExecuteCommandBuffer(cmd);
                CommandBufferPool.Release(cmd);
            }
            //创建网格
            Mesh CreateMesh()
            {
                Mesh mesh = new Mesh();
                mesh.vertices = new Vector3[4] { new Vector3(1, 1, 1), new Vector3(-1, 1, 1), new Vector3(-1, 1, -1), new Vector3(1, 1, -1) };
                int[] indices = new int[8] { 0, 1, 1, 2, 2, 3, 3, 0 };
                mesh.SetIndices(indices, MeshTopology.Lines, 0);
                return mesh;
            }
        }
        //渲染画面
        class CustomRenderPassRT : ScriptableRenderPass
        {
            static string RtName = "_TestRT";
            //获取着色器属性名称的唯一标识符。
            static int RT_ID = Shader.PropertyToID(RtName);
            public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
            {
                //新建一个RenderTextureDescriptor
                RenderTextureDescriptor textureDescriptor = new RenderTextureDescriptor(1920, 1080, RenderTextureFormat.Default, 0);
                //获取临时渲染纹理
                cmd.GetTemporaryRT(RT_ID, textureDescriptor);
            }
            public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
            {
                CommandBuffer cmd = CommandBufferPool.Get("ShowRT");
                //下面三段实现效果一样
                cmd.Blit(renderingData.cameraData.renderer.cameraColorTarget, RT_ID);
               // cmd.Blit(RenderTargetHandle.CameraTarget.Identifier(), RT_ID);
               // cmd.Blit(colorAttachment, RT_ID);
                context.ExecuteCommandBuffer(cmd);
                CommandBufferPool.Release(cmd);
            }
            public override void OnCameraCleanup(CommandBuffer cmd)
            {
                cmd.ReleaseTemporaryRT(RT_ID);
            }
        }
    
        CustomRenderShaderPostPass m_ScriptablePassPost;
        CustomRenderPassCreateMesh m_ScriptablePassCreateMesh;
        CustomRenderPassRT m_ScriptablePassRenderTextrue;
        public Shader shaderPost;
        public Shader shaderMesh;
        /// 
        public override void Create()
        {
            #region 后处理效果
            m_ScriptablePassPost = new CustomRenderShaderPostPass();
            //通过创建一个渲染材质
            m_ScriptablePassPost._Material = new Material(shaderPost);
            //定义渲染的位置
            m_ScriptablePassPost.renderPassEvent = RenderPassEvent.AfterRendering;
            #endregion
    
            #region 创建网格
            m_ScriptablePassCreateMesh = new CustomRenderPassCreateMesh();
            m_ScriptablePassCreateMesh._Material = new Material(shaderMesh);
            m_ScriptablePassCreateMesh.renderPassEvent = RenderPassEvent.AfterRenderingOpaques;
            #endregion
    
            #region 渲染画面
            m_ScriptablePassRenderTextrue = new CustomRenderPassRT();
            m_ScriptablePassRenderTextrue.renderPassEvent = RenderPassEvent.AfterRendering;
            #endregion
    
        }
    
        // 这里你可以在渲染器中注入一个或多个渲染通道。
        //每一帧都执行
        public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
        {
            //把实例化的CustomRenderPass插入渲染管线
            renderer.EnqueuePass(m_ScriptablePassRenderTextrue);
            renderer.EnqueuePass(m_ScriptablePassPost);
            renderer.EnqueuePass(m_ScriptablePassCreateMesh);
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129

    五、RenderFeatrue参数赋值

    1、VolumeComponent

    在Volume中提供Render Feature读取参数数据,通过VolumeManager单列,拿到stack,可以直接取得Volume中的数据。

    以修改上文后处理的饱和度和对比度为例

    1)创建一个全局的Global Volume

    右击Hierarchy面板空白处选择Volume→Global Volume

    2)自定义一个VolumeComponent
    using UnityEngine.Rendering;
    
    public class VolumeComponentTest : VolumeComponent
    {
        public ClampedFloatParameter Saturation = new ClampedFloatParameter(1f, 0, 3);
        public ClampedFloatParameter Contrast = new ClampedFloatParameter(1f, 0, 3);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    可以在Volume中添加VolumeComponentTest组件

    3)在shader中添加控制的参数

    这添加了Saturation和Contrast两个控制参数

    Shader "Unlit/SaturationContrastShader"
    {
        Properties
        {
            _Saturation("Saturation", Range(0, 3)) = 1.0
            _Contrast("Contrast", Range(0, 3)) = 1.0
        }
        SubShader
        {
            Pass
            {
               ZTest Always ZWrite Off
                CGPROGRAM
    
                #pragma vertex vert_img  // 使用内置的vert_img顶点着色器
                #pragma fragment frag
    
                #include "UnityCG.cginc"
    
                float _Saturation;
                float _Contrast;
                sampler2D _CameraColorTexture; 
                //饱和度
                fixed3   Saturation_float(float3 In, float Saturation)
                {
                    float luma = dot(In, float3(0.2126729, 0.7151522, 0.0721750));
                    return luma.xxx + Saturation.xxx * (In - luma.xxx);
                }
                //对比度
                fixed3  Contrast_float(float3 In, float Contrast)
                {
                    float midpoint = pow(0.5, 2.2);
                    return (In - midpoint) * Contrast + midpoint;
                }
    
                fixed4 frag (v2f_img i) : SV_Target
                {
                    fixed4 col = tex2D(_CameraColorTexture, i.uv);
                    fixed3  Saturation =  Saturation_float(col, _Saturation);
                    fixed3  Contrast = Saturation_float(Saturation, _Contrast);
                    return fixed4(Contrast.x, Contrast.y, Contrast.z,0.1);
                }
                ENDCG
            }
        }
       FallBack Off
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    用shaderGraph实现的也是一样的添加两个参数

    4)在RenderFeatrue中读取参数

    对CustomRenderShaderPostPass修过如下

      class CustomRenderShaderPostPass : ScriptableRenderPass
        {  
            //定义渲染材质,通过Create方法赋值
            public Material _Material;
            //定义一个VolumeComponentTest
            VolumeComponentTest volumeComponentTest;
            public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
            {
                //读取VolumeManager的单列取得stack
                var stack = VolumeManager.instance.stack;
                //为volumeComponentTest赋值
                volumeComponentTest = stack.GetComponent();
                if (!volumeComponentTest) return;
                //直接从volumeComponentTest中读取数据
                _Material.SetFloat("_Saturation", volumeComponentTest.Saturation.value);
                _Material.SetFloat("_Contrast", volumeComponentTest.Contrast.value);
                //创建一个CommandBuffer
                CommandBuffer cmd = CommandBufferPool.Get("ShowShader");
                //这里有一个疑问,渲染标识符不管怎么传都不影响结果
                cmd.Blit(colorAttachment, RenderTargetHandle.CameraTarget.Identifier(), _Material);
                //执行CommandBuffer
                context.ExecuteCommandBuffer(cmd);
                //回收CommandBuffer
                CommandBufferPool.Release(cmd);
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    实现效果

    2、代码直接赋值

    在RenderFeatrue中开放参数,用代码直接赋值

    以后处理的饱和度和对比度为例

    1)开放参数

    在CustomRenderPassFeatureTest和CustomRenderShaderPostPass下分别定义饱和度和对比度,并赋值

    public class CustomRenderPassFeatureTest : ScriptableRendererFeature
    {
      
        //后处理效果
        class CustomRenderShaderPostPass : ScriptableRenderPass
        {  
            //定义渲染材质,通过Create方法赋值
            public Material _Material;
            public float _Contrast;
            public float _Saturation;
            public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
            {
                _Material.SetFloat("_Saturation", _Saturation);
                _Material.SetFloat("_Contrast", _Contrast);
                //创建一个CommandBuffer
                CommandBuffer cmd = CommandBufferPool.Get("ShowShader");
                //这里有一个疑问,渲染标识符不管怎么传都不影响结果
                cmd.Blit(colorAttachment, RenderTargetHandle.CameraTarget.Identifier(), _Material);
                //执行CommandBuffer
                context.ExecuteCommandBuffer(cmd);
                //回收CommandBuffer
                CommandBufferPool.Release(cmd);
            }
        }
        CustomRenderShaderPostPass m_ScriptablePassPost;
    
        public Shader shaderPost;
        public float Saturation;
        public float Contrast;
        /// 
        public override void Create()
        {
            #region 后处理效果
            m_ScriptablePassPost = new CustomRenderShaderPostPass();
            //通过创建一个渲染材质
            m_ScriptablePassPost._Material = new Material(shaderPost);
            //将饱和度和对比度赋值给CustomRenderShaderPostPass
            m_ScriptablePassPost._Contrast = Contrast;
            m_ScriptablePassPost._Saturation = Saturation;
            //定义渲染的位置
            m_ScriptablePassPost.renderPassEvent = RenderPassEvent.AfterRendering;
    
            #endregion
        }
    
        // 这里你可以在渲染器中注入一个或多个渲染通道。
        //每一帧都执行
        public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
        {
            //把实例化的CustomRenderPass插入渲染管线
            renderer.EnqueuePass(m_ScriptablePassPost);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    2)对参数进行修改

    //得到RenderFeatrue    
    CustomRenderPassFeatureTest custom=renderData.rendererFeatures.OfType().FirstOrDefault();
    //对值进行修改
    custom.Saturation =0;
    custom.Contrast =0;
    //设置数据
    custom.SetParam();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
  • 相关阅读:
    前端react 18.2整合ckeditor富文本编辑器——配置插件、自定义toolbar工具栏
    最优秀的完整的数字音频工作站水果音乐FL Studio21.1.1.3750中文解锁版
    网络库OKHttp(1)流程+拦截器
    Pytorch - 数据增广
    前端Vue的循环forEach等各种循环下,取每一项下面的有个对象里面的值方法
    使用 Docker 自建一款怀旧游戏之 - 扫雷
    java 单例模式
    能够1年涨薪2次的软件测试工程师,他到底强在哪里?
    物联网平台建设方案
    2022-8-30 第七小组 学习日记 (day54)JavaWeb、Servlet、HTTP-请求 响应、乱码问题
  • 原文地址:https://blog.csdn.net/dxs1990/article/details/133647980