找回密码
 立即注册
首页 业界区 安全 【URP】Unity[RendererFeatures]渲染对象RenderObjects ...

【URP】Unity[RendererFeatures]渲染对象RenderObjects

石娅凉 2025-11-20 11:00:08
【从UnityURP开始探索游戏渲染】专栏-直达
RenderObjects的定义与作用

RenderObjects是URP提供的RendererFeature之一,允许开发者在不编写代码的情况下对渲染管线进行定制。它通过配置参数实现选择性渲染特定层级的物体、控制渲染顺序、重载材质或渲染状态等功能57。其核心用途包括:

  • 层级过滤‌:仅渲染指定LayerMask的物体
  • 渲染时机控制‌:通过Event参数插入到渲染管线的不同阶段(如AfterRenderingOpaques)
  • 材质替换‌:使用Override Material覆盖原有材质
  • 多Pass渲染‌:配合Shader的LightMode标签实现描边等效果
发展历史


  • 初始版本(2020年前)作为LWRP实验性功能引入
  • 2020年URP 7.x版本正式集成,提供基础层过滤和材质替换
  • 2021年后增强深度/模板控制,支持透明物体处理
  • 2022年优化API结构,明确ScriptableRendererFeature与RenderPass的分离
原理

底层原理


  • 架构层级
    RenderObjects通过继承ScriptableRendererFeature和ScriptableRenderPass实现管线扩展,核心逻辑在Execute()方法中通过CommandBuffer提交绘制指令。其本质是通过URP的ScriptableRenderContext调度GPU渲染命令,与内置管线不同之处在于采用可编程的轻量级渲染管线架构。
  • 渲染流程控制
    通过RenderPassEvent枚举插入到URP的固定管线阶段(如AfterRenderingOpaques),底层会触发以下操作:

    • 调用ConfigureTarget()设置渲染目标
    • 使用FilteringSettings过滤指定Layer的物体
    • 通过DrawingSettings配置Shader Pass和排序规则

  • 材质替换机制
    当启用Override Material时,URP会临时替换原始材质的Shader,但保留物体的顶点数据。该过程通过MaterialPropertyBlock实现动态参数传递,避免材质实例化开销。
实现示例


  • OutlineFeature.cs
    1. using UnityEngine;
    2. using UnityEngine.Rendering;
    3. using UnityEngine.Rendering.Universal;
    4. public class OutlineFeature : ScriptableRendererFeature {
    5.     class OutlinePass : ScriptableRenderPass {
    6.         private Material _outlineMat;
    7.         private LayerMask _layerMask;
    8.         private FilteringSettings _filteringSettings;
    9.         public OutlinePass(Material mat, LayerMask mask) {
    10.             _outlineMat = mat;
    11.             _layerMask = mask;
    12.             _filteringSettings = new FilteringSettings(RenderQueueRange.opaque, _layerMask);
    13.             renderPassEvent = RenderPassEvent.AfterRenderingOpaques;
    14.         }
    15.         public override void Execute(ScriptableRenderContext context, ref RenderingData data) {
    16.             var drawingSettings = CreateDrawingSettings(
    17.                 new ShaderTagId("UniversalForward"),
    18.                 ref data,
    19.                 SortingCriteria.CommonOpaque
    20.             );
    21.             drawingSettings.overrideMaterial = _outlineMat;
    22.             context.DrawRenderers(data.cullResults, ref drawingSettings, ref _filteringSettings);
    23.         }
    24.     }
    25.     [SerializeField] private Material _outlineMaterial;
    26.     [SerializeField] private LayerMask _outlineLayers = 1;
    27.     private OutlinePass _pass;
    28.     public override void Create() => _pass = new OutlinePass(_outlineMaterial, _outlineLayers);
    29.     public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData data)
    30.         => renderer.EnqueuePass(_pass);
    31. }
    复制代码
  • Outline.shader
    1. Shader "Custom/Outline" {
    2.     Properties {
    3.         _OutlineColor("Color", Color) = (1,0,0,1)
    4.         _OutlineWidth("Width", Range(0,0.1)) = 0.03
    5.     }
    6.     SubShader {
    7.         Tags { "RenderType"="Opaque" "Queue"="Geometry+100" }
    8.         Pass {
    9.             Cull Front
    10.             ZWrite Off
    11.             CGPROGRAM
    12.             #pragma vertex vert
    13.             #pragma fragment frag
    14.             #include "UnityCG.cginc"
    15.             float _OutlineWidth;
    16.             fixed4 _OutlineColor;
    17.             struct appdata {
    18.                 float4 vertex : POSITION;
    19.                 float3 normal : NORMAL;
    20.             };
    21.             v2f vert(appdata v) {
    22.                 v2f o;
    23.                 v.vertex.xyz += v.normal * _OutlineWidth;
    24.                 o.pos = UnityObjectToClipPos(v.vertex);
    25.                 return o;
    26.             }
    27.             fixed4 frag(v2f i) : SV_Target {
    28.                 return _OutlineColor;
    29.             }
    30.             ENDCG
    31.         }
    32.     }
    33. }
    复制代码
关键流程解析


  • 渲染指令提交
    DrawRenderers方法内部会构建BatchRendererGroup,将CPU侧的渲染数据批量提交至GPU,相比直接使用CommandBuffer更高效。
  • 深度测试控制
    示例中ZWrite Off禁用深度写入,使描边始终显示在原始物体表面,该技术也常用于解决透明物体渲染顺序问题。
  • 多Pass协作
    URP会先执行默认的Forward渲染Pass,再执行RenderObjects插入的Pass,通过RenderPassEvent控制执行顺序
完整实现流程示例


  • OutlineFeature.cs
    1. using UnityEngine;
    2. using UnityEngine.Rendering;
    3. using UnityEngine.Rendering.Universal;
    4. public class OutlineFeature : ScriptableRendererFeature {
    5.     class OutlinePass : ScriptableRenderPass {
    6.         private Material outlineMat;
    7.         private LayerMask layerMask;
    8.         private RenderTargetIdentifier source;
    9.         public OutlinePass(Material mat, LayerMask mask) {
    10.             outlineMat = mat;
    11.             layerMask = mask;
    12.             renderPassEvent = RenderPassEvent.AfterRenderingOpaques;
    13.         }
    14.         public override void Execute(ScriptableRenderContext context, ref RenderingData data) {
    15.             CommandBuffer cmd = CommandBufferPool.Get("OutlinePass");
    16.             var drawSettings = CreateDrawingSettings(
    17.                 new ShaderTagId("UniversalForward"),
    18.                 ref data, SortingCriteria.CommonOpaque);
    19.             var filterSettings = new FilteringSettings(RenderQueueRange.opaque, layerMask);
    20.             context.DrawRenderers(data.cullResults, ref drawSettings, ref filterSettings);
    21.             CommandBufferPool.Release(cmd);
    22.         }
    23.     }
    24.     [SerializeField] private Material outlineMaterial;
    25.     [SerializeField] private LayerMask outlineLayers;
    26.     private OutlinePass pass;
    27.     public override void Create() {
    28.         pass = new OutlinePass(outlineMaterial, outlineLayers);
    29.     }
    30.     public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData data) {
    31.         renderer.EnqueuePass(pass);
    32.     }
    33. }
    复制代码
  • Outline.shader
    1. Shader "Custom/Outline" {
    2.     Properties {
    3.         _OutlineColor("Color", Color) = (1,1,1,1)
    4.         _OutlineWidth("Width", Range(0,0.1)) = 0.05
    5.     }
    6.     SubShader {
    7.         Tags { "RenderType"="Opaque" "LightMode"="UniversalForward" }
    8.         Pass {
    9.             CGPROGRAM
    10.             // Vertex expansion logic...
    11.             ENDCG
    12.         }
    13.     }
    14. }
    复制代码
参数详解与用例

参数说明应用场景‌Event‌渲染时机(如BeforeRenderingPostProcessing)控制特效叠加顺序‌LayerMask‌目标渲染层级仅对敌人/UI层描边‌Override Material‌替换材质角色进入阴影区切换材质‌Depth Test‌深度测试模式解决透明物体遮挡问题‌Shader Passes‌匹配的Shader LightMode标签多Pass渲染(如"UniversalForward")配置步骤


  • 创建URP Asset并启用Renderer Features
  • 添加RenderObjects Feature到Forward Renderer
  • 配置Event为AfterRenderingOpaques(不透明物体)或AfterRenderingTransparents(透明物体)
  • 指定目标Layer和替换材质
  • 调整Depth/Stencil参数解决遮挡问题
典型应用包括:角色描边、场景分块渲染、特殊效果叠加(如受伤高亮)等。通过组合不同Event和LayerMask可实现复杂的渲染管线控制
<blockquote>
【从UnityURP开始探索游戏渲染】专栏-直达
(欢迎点赞留言探讨,更多人加入进来能更加完善这个探索的过程,
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册