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

实现自定义阴影图时,如何不依赖Camera组件调用ScriptableRenderContext.Cull?

解决无Camera组件下获取CullingResults的问题

错误的核心原因是ScriptableCullingParameters需要关联一个Camera实例来处理LOD衰减和渲染器上下文逻辑,哪怕你不使用场景中的Camera组件,也可以通过创建临时的、未挂载到场景的Camera对象来满足要求。

修改步骤与代码示例

// 创建临时Camera(无需挂载到任何GameObject)
var tempCamera = new Camera();
tempCamera.transform.SetPositionAndRotation(_transform.position, _transform.rotation);
tempCamera.orthographic = true;
tempCamera.nearClipPlane = _nearClip;
tempCamera.farClipPlane = _farClip;
tempCamera.projectionMatrix = _projectionMatrix; // 绑定自定义投影矩阵

// 用临时Camera初始化裁剪参数(自动填充必要上下文)
if (!ScriptableCullingParameters.TryGetCullingParameters(tempCamera, out var cullParams))
{
    Debug.LogError("无法获取裁剪参数");
    Object.DestroyImmediate(tempCamera);
    return;
}

// 自定义裁剪配置(按需调整)
cullParams.cullingOptions = CullingOptions.None;
cullParams.maximumVisibleLights = 0;
// 替换裁剪平面(如果需要自定义)
var nearClipPlane = new Plane(Vector3.forward, tempCamera.transform.position + Vector3.forward * _nearClip);
var farClipPlane = new Plane(-Vector3.forward, tempCamera.transform.position + Vector3.forward * _farClip);
cullParams.cullingPlaneCount = 2;
cullParams.SetCullingPlane(0, nearClipPlane);
cullParams.SetCullingPlane(1, farClipPlane);

// 执行裁剪获取结果
var cullData = context.Cull(ref cullParams);

// 后续渲染命令保持逻辑,注意RendererListDesc使用临时Camera
_commandBuffer.SetRenderTarget(_depthTexture);
_commandBuffer.ClearRenderTarget(true, true, Color.clear);
_commandBuffer.SetViewMatrix(_viewMatrix);
_commandBuffer.SetProjectionMatrix(_projectionMatrix);

var rendererListDesc = new RendererListDesc(new ShaderTagId("UniversalForward"), cullData, tempCamera)
{
    sortingCriteria = SortingCriteria.CommonOpaque,
    rendererConfiguration = PerObjectData.None,
    renderQueueRange = RenderQueueRange.opaque,
    overrideMaterial = _testMaterial
};

var rendererList = context.CreateRendererList(rendererListDesc);
_commandBuffer.DrawRendererList(rendererList);

context.ExecuteCommandBuffer(_commandBuffer);
_commandBuffer.Clear();

// 销毁临时Camera,避免内存泄漏
Object.DestroyImmediate(tempCamera);

关键注意点

  • 临时Camera仅用于提供裁剪所需的上下文,不会在场景中显示或产生额外开销
  • 使用TryGetCullingParameters初始化参数比手动赋值更可靠,能自动处理LOD、视锥体等基础逻辑
  • 用完必须销毁临时Camera,防止内存泄漏
  • 原始代码中裁剪平面的法线方向可能有误,已在示例中修正(近裁剪平面法线指向相机前方,远裁剪平面法线指向相机后方)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 08:30:20