Unity SRP自定义渲染通道中DrawRenderers排序异常问题求助
自定义渲染通道DrawRenderers排序异常问题
我在自定义渲染通道中使用DrawRenderers函数时遇到排序错误,以下是该通道的Execute函数代码:
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) { CommandBuffer cmd = CommandBufferPool.Get("VisibilityPass"); SortingSettings ss = new SortingSettings(renderingData.cameraData.camera) { criteria = SortingCriteria.BackToFront }; DrawingSettings drawSettings = new DrawingSettings(new ShaderTagId("UniversalForward"), ss) { overrideShader = visibilityShader }; FilteringSettings filteringSettings = FilteringSettings.defaultValue; cmd.ClearRenderTarget(true, true, new Color(0, 0, 1, 1)); context.ExecuteCommandBuffer(cmd); context.DrawRenderers(renderingData.cullResults, ref drawSettings, ref filteringSettings); context.Submit(); CommandBufferPool.Release(cmd); }
预期效果是将场景渲染到RenderTexture中,用指定Shader覆盖所有物体(场景物体纯黑,立方体纯红),RenderTexture显示在屏幕左上角。多数情况功能正常,但当相机与立方体处于平面中心两侧时,排序出现错误。怀疑是SortingSettings的问题,但不确定具体原因,求排查错误。
正常效果:
异常效果:
问题原因分析
你当前使用的SortingCriteria.BackToFront是基于物体包围盒中心的深度值进行排序,而非像素级的深度测试。当相机和立方体分别在平面两侧时,平面的包围盒中心可能比立方体更靠近相机,导致平面被优先绘制,覆盖了本应在前方的立方体。同时代码未启用深度测试与深度写入,完全依赖排序结果,没有硬件深度缓冲的兜底判断,进一步放大了排序误差。
修复方案
1. 启用深度测试与深度写入
在CommandBuffer中添加深度相关设置,让硬件深度缓冲处理遮挡关系:
cmd.ClearRenderTarget(true, true, new Color(0, 0, 1, 1)); // 启用深度测试和深度写入 cmd.SetDepthState(DepthState.Default);
2. 调整SortingCriteria排序规则
使用更适合不透明物体的通用排序规则,结合距离与渲染队列,减少排序误差:
SortingSettings ss = new SortingSettings(renderingData.cameraData.camera) { criteria = SortingCriteria.CommonOpaque };
3. 精确指定过滤范围
确保FilteringSettings只处理目标渲染队列的物体,避免不必要的干扰:
FilteringSettings filteringSettings = new FilteringSettings(RenderQueueRange.opaque);
修复后完整代码示例
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) { CommandBuffer cmd = CommandBufferPool.Get("VisibilityPass"); SortingSettings ss = new SortingSettings(renderingData.cameraData.camera) { criteria = SortingCriteria.CommonOpaque }; DrawingSettings drawSettings = new DrawingSettings(new ShaderTagId("UniversalForward"), ss) { overrideShader = visibilityShader }; FilteringSettings filteringSettings = new FilteringSettings(RenderQueueRange.opaque); cmd.ClearRenderTarget(true, true, new Color(0, 0, 1, 1)); cmd.SetDepthState(DepthState.Default); context.ExecuteCommandBuffer(cmd); context.DrawRenderers(renderingData.cullResults, ref drawSettings, ref filteringSettings); context.Submit(); CommandBufferPool.Release(cmd); }
内容的提问来源于stack exchange,提问作者Gabriel Bacon
相关产品推荐
相关产品推荐

