【URP】Unity 插入自定义RenderPass

【从UnityURP开始探索游戏渲染】专栏-直达

自定义渲染通道是一种改变通用渲染管道(URP)如何渲染场景或场景中的对象的方法。自定义呈现通道(RenderPass)包含自己的Render代码,可以在注入点将其添加到RenderPass中。

添加自定义呈现通道(RenderPass):

  • 使用Scriptable render pass API创建自定义render pass的代码。
  • 将自定的render pass注入到URP管线中的指定注入点中,有两种方式:
    • RenderPipelineManager API注入自定义渲染通道
    • 或者通过创建一个可脚本化的RendererFeature添加到URP渲染器中。

使用Scriptable render pass API创建自定义render pass

  • Example custom render pass

    cs 复制代码
    using UnityEngine;
    using UnityEngine.Rendering;
    using UnityEngine.Rendering.Universal;
    
    internal class ColorBlitPass : ScriptableRenderPass
    {
        ProfilingSampler m_ProfilingSampler = new ProfilingSampler("ColorBlit");
        Material m_Material;
        RTHandle m_CameraColorTarget;
        float m_Intensity;
    
        public ColorBlitPass(Material material)
        {
            m_Material = material;
            renderPassEvent = RenderPassEvent.BeforeRenderingPostProcessing;
        }
    
        public void SetTarget(RTHandle colorHandle, float intensity)
        {
            m_CameraColorTarget = colorHandle;
            m_Intensity = intensity;
        }
    
        public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
        {
            ConfigureTarget(m_CameraColorTarget);
        }
    
        public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
        {
            var cameraData = renderingData.cameraData;
            if (cameraData.camera.cameraType != CameraType.Game)
                return;
    
            if (m_Material == null)
                return;
    
            CommandBuffer cmd = CommandBufferPool.Get();
            using (new ProfilingScope(cmd, m_ProfilingSampler))
            {
                m_Material.SetFloat("_Intensity", m_Intensity);
                Blitter.BlitCameraTexture(cmd, m_CameraColorTarget, m_CameraColorTarget, m_Material, 0);
            }
            context.ExecuteCommandBuffer(cmd);
            cmd.Clear();
    
            CommandBufferPool.Release(cmd);
        }
    }

将自定的render pass注入到URP管线中的指定注入点中

RenderPipelineManager API注入自定义渲染通道

  • 通过RenderPipelineManager的注入点委托提供执行时机,加上Camera的EnqueuePass方法注入自定义RenderPass。

    cs 复制代码
    public class EnqueuePass : MonoBehaviour
    {
        [SerializeField] private BlurSettings settings;    
        private BlurRenderPass blurRenderPass;
    
        private void OnEnable()
        {
            ...
            blurRenderPass = new BlurRenderPass(settings);
            // Subscribe the OnBeginCamera method to the beginCameraRendering event.
            RenderPipelineManager.beginCameraRendering += OnBeginCamera;
        }
    
        private void OnDisable()
        {
            RenderPipelineManager.beginCameraRendering -= OnBeginCamera;
            blurRenderPass.Dispose();
            ...
        }
    
        private void OnBeginCamera(ScriptableRenderContext context, Camera cam)
        {
            ...
            // Use the EnqueuePass method to inject a custom render pass
            cam.GetUniversalAdditionalCameraData()
                .scriptableRenderer.EnqueuePass(blurRenderPass);
        }
    }

创建一个可脚本化的RendererFeature

此示例执行将屏幕染成绿色的全屏blit。

  • 要创建自定义渲染通道,创建一个名为ColorBlitPass.cs的新c#脚本,然后从示例自定义渲染通道部分粘贴代码。

    • 注意:这个例子使用了Blitter API。不要使用CommandBuffer。URP中的Blit API。更多信息请参考Blit。
    • 使用上面定义好的定制Render Pass
  • 要创建Scriptable RendererFeature,将自定义渲染通道添加到渲染循环中,请创建一个名为ColorBlitRendererFeature.cs的新c#脚本,然后将示例Scriptable RendererFeature部分中的代码粘贴进来。

    • Example Scriptable Renderer Feature Scriptable Renderer Feature 添加 render pass 到渲染循环.

      cs 复制代码
      using UnityEngine;
      using UnityEngine.Rendering;
      using UnityEngine.Rendering.Universal;
      
      internal class ColorBlitRendererFeature : ScriptableRendererFeature
      {
          public Shader m_Shader;
          public float m_Intensity;
      
          Material m_Material;
      
          ColorBlitPass m_RenderPass = null;
      
          public override void AddRenderPasses(ScriptableRenderer renderer,
                                          ref RenderingData renderingData)
          {
              if (renderingData.cameraData.cameraType == CameraType.Game)
                  renderer.EnqueuePass(m_RenderPass);
          }
      
          public override void SetupRenderPasses(ScriptableRenderer renderer,
                                              in RenderingData renderingData)
          {
              if (renderingData.cameraData.cameraType == CameraType.Game)
              {
                  // Calling ConfigureInput with the ScriptableRenderPassInput.Color argument
                  // ensures that the opaque texture is available to the Render Pass.
                  m_RenderPass.ConfigureInput(ScriptableRenderPassInput.Color);
                  m_RenderPass.SetTarget(renderer.cameraColorTargetHandle, m_Intensity);
              }
          }
      
          public override void Create()
          {
              m_Material = CoreUtils.CreateEngineMaterial(m_Shader);
              m_RenderPass = new ColorBlitPass(m_Material);
          }
      
          protected override void Dispose(bool disposing)
          {
              CoreUtils.Destroy(m_Material);
          }
      }
  • 要创建将像素染成绿色的着色器代码,请创建一个着色器文件,然后从示例着色器部分粘贴代码。

  • Example shader

    • 着色器执行渲染的GPU端。它从相机中采样颜色纹理,然后输出绿色值设置为所选强度的颜色。
      注意:与Blitter API一起使用的着色器必须是手工编码的着色器。图形着色器与Blitter API不兼容。

      cpp 复制代码
      Shader "ColorBlit"
      {
          SubShader
          {
              Tags { "RenderType"="Opaque" "RenderPipeline" = "UniversalPipeline"}
              LOD 100
              ZWrite Off Cull Off
              Pass
              {
                  Name "ColorBlitPass"
      
                  HLSLPROGRAM
                  #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
                  
                  // The Blit.hlsl file provides the vertex shader (Vert),
                  // the input structure (Attributes) and the output structure (Varyings)
                  #include "Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blit.hlsl"
      
                  #pragma vertex Vert
                  #pragma fragment frag
      
                  // Set the color texture from the camera as the input texture
                  TEXTURE2D_X(_CameraOpaqueTexture);
                  SAMPLER(sampler_CameraOpaqueTexture);
      
                  // Set up an intensity parameter
                  float _Intensity;
      
                  half4 frag (Varyings input) : SV_Target
                  {
                      UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
      
                      // Sample the color from the input texture
                      float4 color = SAMPLE_TEXTURE2D_X(_CameraOpaqueTexture, sampler_CameraOpaqueTexture, input.texcoord);
      
                      // Output the color from the texture, with the green value set to the chosen intensity
                      return color * float4(0, _Intensity, 0, 1);
                  }
                  ENDHLSL
              }
          }
      }
  • 将ColorBlitRendererFeature添加到当前URP Renderer资源中。有关更多信息,请参阅向URP渲染器添加渲染器功能。

  • 要更改亮度,请调整Color Blit Renderer Feature组件中的Intensity属性。

注意:如果项目使用XR,为了使示例可视化,在项目中安装MockHMD XR插件包,然后将渲染模式属性设置为单通道实例化。


https://docs.unity3d.com/Packages/com.unity.render-pipelines.universal@14.0/manual/renderer-features/custom-rendering-pass-workflow-in-urp.html


【从UnityURP开始探索游戏渲染】专栏-直达

(欢迎点赞留言探讨,更多人加入进来能更加完善这个探索的过程,🙏)

相关推荐
黑客影儿5 小时前
使用UE5开发2.5D开放世界战略养成类游戏的硬件配置指南
开发语言·c++·人工智能·游戏·智能手机·ue5·游戏引擎
霜绛6 小时前
Unity笔记(六)——Mathf、三角函数、坐标系、向量
笔记·学习·unity·游戏引擎
SmalBox7 小时前
【渲染流水线】[逐片元阶段]-[混合Blend]以UnityURP为例
unity·渲染
DanmF--8 小时前
Unity中的特殊文件夹
unity·c#·游戏引擎
野区捕龙为宠9 小时前
Unity Netcode for GameObjects(多人联机小Demo)
java·unity·游戏引擎
相信神话20211 天前
Godot Shader 中 mix 函数的用法
游戏引擎·godot
郝学胜-神的一滴1 天前
Horse3D游戏引擎研发笔记(七):在QtOpenGL环境下,使用改进的Uniform变量管理方式绘制多彩四边形
c++·3d·unity·游戏引擎·图形渲染·虚幻·unreal engine
巨龙之路1 天前
Unity的Cursor.lockState
unity·游戏引擎
★YUI★1 天前
学习制作记录(选项UI以及存档系统)8.24
学习·游戏·ui·unity·c#