You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity URP自定义ScriptableRenderPass渲染GameObject问题排查

两种实现方式的问题分析与解决方案

第一种实现方式(CommandBuffer.DrawRenderer)

存在的问题

  1. 无光照效果:直接调用DrawRenderer时,没有触发URP材质中处理光照的Pass,也未向GPU传递URP所需的光照常量数据(比如主光源信息、光照矩阵等),导致材质无法计算光照。
  2. 黑色方块异常:未配置正确的渲染状态(如深度测试、深度写入),物体渲染时无法正确处理遮挡;同时未指定URP专属的渲染Pass,使用了材质的默认Pass导致渲染异常。

解决代码与说明

public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
{
    CommandBuffer cmd = CommandBufferPool.Get("EnemyClearDepthPass");
    var camera = renderingData.cameraData.camera;
    
    // 同步相机的MVP、视口等属性到GPU
    context.SetupCameraProperties(camera);
    // 配置深度测试与写入,避免遮挡错误
    cmd.SetDepthTest(CompareFunction.LessEqual);
    cmd.SetDepthWrite(true);

    // 指定URP正向渲染的Pass
    int forwardPassIndex = Shader.PropertyToID("UniversalForward");

    foreach (var renderer in _associatedObjects)
    {
        if (renderer.isVisible)
        {
            // 使用URP的正向Pass渲染,确保光照计算生效
            cmd.DrawRenderer(renderer, renderer.sharedMaterial, 0, forwardPassIndex);
        }
    }

    context.ExecuteCommandBuffer(cmd);
    CommandBufferPool.Release(cmd);
    // 提交渲染上下文,确保命令执行
    context.Submit();
}

第二种实现方式(ScriptableRenderContext.DrawRenderers)

存在的问题

  1. DrawingSettings配置缺失:未指定URP的ShaderTagId,URP无法识别要渲染的材质Pass;同时SortingSettings未关联相机,导致排序逻辑失效,物体可能被错误剔除。
  2. RenderStateBlock过度覆盖:设置RenderStateMask.Everything会清空URP默认的深度、混合等渲染状态,导致物体无法正常渲染。
  3. Pass执行时机未指定:默认执行时机可能处于渲染流程的错误阶段,无法获取正确的剔除结果与渲染上下文。

解决代码与说明

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

public class JustDrawSomethingPls : ScriptableRendererFeature
{
    class DrawEverythingPass : ScriptableRenderPass
    {
        // 指定URP正向渲染的ShaderTag
        private readonly ShaderTagId _forwardTag = new ShaderTagId("UniversalForward");

        public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
        {
            // 基于当前相机初始化排序设置,确保渲染顺序正确
            SortingSettings sortingSettings = new SortingSettings(renderingData.cameraData.camera)
            {
                criteria = SortingCriteria.CommonOpaque
            };

            // 初始化DrawingSettings,绑定URP的ShaderPass与排序规则
            DrawingSettings drawingSettings = new DrawingSettings(_forwardTag, sortingSettings)
            {
                mainLightIndex = renderingData.lightData.mainLightIndex
            };

            // 配置过滤规则,可替换layerMask为目标Layer的掩码(如1 << LayerMask.NameToLayer("Enemy"))
            FilteringSettings filteringSettings = new FilteringSettings(RenderQueueRange.opaque)
            {
                layerMask = int.MaxValue,
                renderingLayerMask = uint.MaxValue
            };

            // 使用默认渲染状态,不覆盖URP的默认配置
            RenderStateBlock renderStateBlock = new RenderStateBlock(RenderStateMask.None);

            // 调用DrawRenderers渲染可见物体
            context.DrawRenderers(renderingData.cullResults, ref drawingSettings, ref filteringSettings, ref renderStateBlock);
            
            // 提交渲染上下文
            context.Submit();
        }
    }

    private DrawEverythingPass _drawEverythingPass;

    public override void Create()
    {
        _drawEverythingPass = new DrawEverythingPass();
        // 指定Pass在不透明物体渲染阶段执行,确保获取正确的剔除结果
        _drawEverythingPass.renderPassEvent = RenderPassEvent.BeforeRenderingOpaques;
    }

    public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
    {
        renderer.EnqueuePass(_drawEverythingPass);
    }
}

额外说明

如果需要渲染特定Layer,只需修改FilteringSettings中的layerMask参数,例如:

filteringSettings.layerMask = 1 << LayerMask.NameToLayer("YourTargetLayer");

内容的提问来源于stack exchange,提问作者danglingPointer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 00:33:10