除了常见的包围盒裁剪(Frustum Culling)和遮挡剔除(Occlusion Culling),还存在以下裁剪算法及其应用场景:

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

1. ‌层级剔除(Layer Culling)‌

  • 原理‌:基于Unity的Layer层级系统,动态禁用特定层级的渲染。例如:

    csharp
    Camera.main.cullingMask &= ~(1 << LayerMask.NameToLayer("UI"));// 剔除UI层
  • 业务逻辑‌:用于场景切换时隐藏非活动层(如隐藏后台场景的NPC层)。

2. ‌距离剔除(Distance Culling)‌

  • 原理‌:根据物体与摄像机的距离动态关闭渲染。URP中可通过LOD Group组件实现:

    csharp
    LODGroup group = GetComponent<LODGroup>();
    group.SetLODs(new LOD[] { new LOD(0.5f, renderers) });// 50%视距时切换LOD
  • 业务逻辑‌:优化开放世界地形渲染,远处物体使用低模或代理网格。

3. ‌视口裁剪(Viewport Culling)‌

  • 原理‌:仅渲染摄像机视口矩形内的内容。通过Camera.rect控制:

    csharp
    camera.rect = new Rect(0, 0, 0.5f, 1);// 仅渲染左半屏
  • 业务逻辑‌:分屏游戏或多画中画场景中减少冗余渲染。

自定义裁剪逻辑实现

‌1. 基于Shader的裁剪‌

  • 实现‌:在顶点着色器中手动丢弃片元:

    hlsl
    if (worldPos.y < _CutoffHeight) discard; // 自定义高度裁剪
  • 应用‌:动态地形破坏效果中隐藏地下部分。

‌2. 脚本驱动的动态剔除‌

  • 示例‌:结合业务逻辑的裁剪系统:

    csharp
    void Update() {
    Renderer renderer = GetComponent<Renderer>();
    renderer.enabled = CheckBusinessLogic();// 自定义条件判断
    }
  • 案例‌:剧情触发时才显示特定物体(如任务道具)。

‌3. 混合剔除策略‌

  • 组合方案‌:在URP的RenderObjects特性中叠加多重条件:

    csharp
    RenderObjects renderFeature = scriptableRenderer.GetFeature<RenderObjects>();
    renderFeature.settings.filterSettings.LayerMask = customMask;// 混合层级+距离

性能优化建议

数据准备‌:将裁剪数据预加载至显存(如通过GraphicsBuffer)减少CPU-GPU传输。

  • GraphicsBuffer 是 Unity 中用于直接操作显存数据的底层 API,通过结构化缓冲区高效存储 GPU 可访问的数据(如裁剪信息、动态网格数据等)

  • 使用GraphicsBuffer预加载裁剪数据到显存的核心步骤示例

    • ‌1. 创建GraphicsBuffer‌

      csharp
      // 定义裁剪数据(如包围盒的8个顶点)
      Vector3[] boundsVertices = CalculateBoundsVertices();// 自定义计算逻辑// 创建GraphicsBuffer(显存缓冲区)
      GraphicsBuffer gpuBuffer = new GraphicsBuffer(
      GraphicsBuffer.Target.Structured,// 缓冲类型
      boundsVertices.Length,// 元素数量sizeof(float) * 3// 每个元素大小(Vector3=3*float)
      );

    • ‌2. 上传数据到显存‌

      csharp
      // 将CPU数据上传至GPU显存
      gpuBuffer.SetData(boundsVertices); // 绑定到Shader(通过全局变量或MaterialPropertyBlock)
      Shader.SetGlobalBuffer("_BoundsBuffer", gpuBuffer);

    • ‌3. Shader中读取裁剪数据‌

      hlsl
      StructuredBuffer<float3> _BoundsBuffer; // 接收显存数据 // 在顶点着色器中判断裁剪
      v2f vert (appdata v) {
      if (ShouldCull(_BoundsBuffer, v.vertex)) // 自定义裁剪逻辑
      clip(-1); // 丢弃片元
      // ...正常渲染逻辑
      }

    • ‌4. 释放资源(关键!)‌

      csharp
      void OnDestroy() {
      gpuBuffer?.Release();// 必须手动释放显存
      }

‌优化技巧‌

  1. 批量处理‌:合并多个物体的裁剪数据到同一Buffer,减少API调用:

    csharp
    GraphicsBuffer combinedBuffer = new GraphicsBuffer(...);
    combinedBuffer.SetData(CombineAllBounds(objects));
  2. 动态更新‌:仅当数据变化时重新上传:

    csharp
    if (boundsChanged) {
    gpuBuffer.SetData(newData);
    }
  3. ComputeShader加速‌:复杂裁剪逻辑可移至ComputeShader:

    hlsl
    // ComputeShader内并行处理裁剪
    [numthreads(64,1,1)]
    void CSMain (uint3 id : SV_DispatchThreadID) {
    if (_BoundsBuffer[id.x].y < _CutoffHeight) {
    _VisibilityBuffer[id.x] = 0; // 标记不可见
    }
    }

‌性能对比‌

方法 CPU-GPU传输量 显存占用 适用场景
传统每帧SetData 数据频繁变化
GraphicsBuffer预加载 静态/半静态裁剪数据
ComputeShader 极低 大规模动态裁剪

‌调试建议‌

  • 使用RenderDoc验证显存数据是否正确上传
  • 通过Profiler监控Graphics.BlitSetData的调用开销
  • 在URP的Frame Debugger中检查裁剪结果
  • 调试工具‌:使用Frame Debugger验证裁剪效果,避免过度剔除。

以上方案可根据项目需求在URP的Forward Renderer Asset中配置或通过C#脚本扩展


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

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

【渲染流水线】[应用阶段]-[定制裁剪]以UnityURP为例的更多相关文章

  1. Shader 入门笔记(二) CPU和GPU之间的通信,渲染流水线

    渲染流水线 1)应用阶段(CPU处理) 首先,准备好场景数据(摄像机位置,视锥体,模型和光源等) 接着,做粗粒度剔除工作. 最后,设置好每个模型的渲染状态(使用的材质,纹理,shader等) 这一阶段 ...

  2. 《UnityShader入门精要》学习笔记之渲染流水线

    第一种分类方式: 图形管道(如下7步): 顶点数据 : 由3D模型传递的三角形网格 顶点着色 : 编写CG程序对各个顶点进行着色 生成几何图元 : 连接特定的顶点生成几何图元,例如连接三个顶点生成一个 ...

  3. Unity Shader 之 渲染流水线

    Unity Shader 之渲染流水线 什么是渲染流水线 一个渲染流程分成3个步骤: 应用阶段(Application stage) 几何阶段(Geometry stage) 光栅化阶段(Raster ...

  4. Unity Shader入门精要学习笔记 - 第2章 渲染流水线

    来源作者:candycat   http://blog.csdn.net/candycat1992/article/ 2.1 综述 渲染流水线的最终目的在于生成或者说是渲染一张二维纹理,即我们在电脑屏 ...

  5. Unity 渲染流水线 :CPU与GPU合作创造的艺术wfd

    前言 对于Unity渲染流程的理解可以帮助我们更好对Unity场景进行性能消耗的分析,进而更好的提升场景渲染的效率,最后提升游戏整体的性能表现 Unity的游戏画面的最终的呈现是由CPU与GPU相互配 ...

  6. Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第五章:渲染流水线

    原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第五章:渲染流水线 学习目标 了解几个用以表达真实场景的标志和2D图像 ...

  7. 移动端 像素渲染流水线与GPU Hack

    什么是 像素渲染流水线 web页面你所写的页面代码是如何被转换成屏幕上显示的像素的.这个转换过程可以归纳为这样的一个流水线,包含五个关键步骤: 1.JavaScript:一般来说,我们会使用JavaS ...

  8. GPU渲染流水线的简单概括

    GPU流水线 主要分为两个阶段:几何阶段和光栅化阶段   几何阶段      顶点着色器 --> 曲面细分着色器(可选)----->几何着色器(可选)----->裁剪-->屏幕 ...

  9. OpenGL渲染流水线

    其实OpenGL的流水线,对我学习来说只能算是一个概念性的东西.毕竟OpenGL也在发展,流水线也不会是一成不变的. 不过理解流水线的过程,重点在于理解每一步的作用,进而可以如何衔接起来,完成整个绘制 ...

  10. UML和模式应用4:初始阶段(4)--需求制品之用例模型模板示例

    1. 前言 UP开发包括四个阶段:初始阶段.细化阶段.构建阶段.移交阶段: UP每个阶段包括 业务建模.需求.设计等科目: 其中需求科目对应的需求制品包括:设想.业务规则.用例模型.补充性规格说明.词 ...

随机推荐

  1. 「Temp」CSP-S 2023 JL 迷惑代码大赏

    (欢迎投稿.) 在 \(213\) 份代码中共查找到 \(21\) 个 //freopen,来自 JL-S00031.JL-S00045.JL-S00047.JL-S00085.JL-S00123.J ...

  2. 设置java程序的守护进程

    1.在服务器执行:crontab -e 命令 2.在出现的界面编写cron表达式  3.编写guard_java_extbork.sh脚本 #!/bin/bash source /etc/profil ...

  3. 图解JavaScript原型:原型链及其分析 02 | JavaScript图解

    ​​ 任何函数既可以看成一个实例对象又可以看成一个函数 作为一个实例对象其隐式原型对象指向其构造函数的显式原型对象 作为一个函数其显式原型对象指向一个空对象 任何一个函数其隐式原型对象指向其构造函数的 ...

  4. React 的 KeepAlive 实战指南:深度解析组件缓存机制

    Vue 的 Keep-Alive 组件是用于缓存组件的高阶组件,可以有效地提高应用性能.它能够使组件在切换时仍能保留原有的状态信息,并且有专门的生命周期方便去做额外的处理.该组件在很多场景非常有用,比 ...

  5. 袋鼠云申杭:数雁EasyDigit,致力成为金融行业数据洞察平台供应商的“领头雁”

    7月28日,以"数智进化,现在即未来"为主题的袋鼠云2022产品发布会于线上正式开幕.发布会上,袋鼠云宣布将集团进行全新升级:从"数字化基础设施供应商",升级为 ...

  6. ArcObjects SDK 023 开发框架搭建-MainApp

    MainApp定义了启动界面,主界面等.主界面的整体流程如下. 1.验证许可. //ArcGIS许可验证 RuntimeManager.Bind(ProductCode.Desktop); var m ...

  7. Solon AI & MCP v3.3.3 发布

    Solon AI Solon AI ,是 Solon 官方推出的 Java AI 应用开发框架.旨在为 Java 开发者提供统一的接口抽象层,简化与 OpenAI.DeepSeek.QWen 等主流 ...

  8. Kong入门学习实践(4)负载均衡与正则路由

    最近在学习Kong网关,因此根据老习惯,我会将我的学习过程记录下来,一来体系化整理,二来作为笔记供将来翻看.由于我司会直接使用Kong企业版,学习过程中我会使用Kong开源版. 本篇,我们学习快速配置 ...

  9. 如何用三层防护体系打造坚不可摧的 API 安全堡垒?

    扫描二维码 关注或者微信搜一搜:编程智域 前端至全栈交流与成长 发现1000+提升效率与开发的AI工具和实用程序:https://tools.cmdragon.cn/ FastAPI 安全与认证综合实 ...

  10. 关于 winform Dev 使用的总结

    treeList控件 1.去除树的头一行:属性–OptionsView–ShowColumns 设为fakse 2.去除树最左列的鼠标箭头列:属性–OptionsView–ShowIndicator设 ...