74.遮挡剔除

74.性能优化-GPU-增强渲染性能-遮挡剔除


74.1 知识点

遮挡剔除的作用

Unity 默认只会进行视锥剔除,即摄像机视锥外的物体不会渲染,但是在视锥内,被其它物体挡住的东西仍然会被渲染。而遮挡剔除就是用来弥补这一点的。

遮挡剔除(Occlusion Culling)的作用:

  1. 让被遮挡、不可见的物体不再进入渲染管线。
  2. 减少 Draw Call、顶点处理、像素填充等开销。
  3. 提升性能,尤其是在室内场景、城市场景、森林这种遮挡很多的环境。

比如玩家在一个房间里,外面的街道模型其实完全看不到,没有必要渲染它们。如果没有遮挡剔除,这些在摄像机视锥范围内的对象依然会送进 GPU 渲染,浪费性能。

简单来说,遮挡剔除弥补了视锥剔除的局限性,让 Unity 可以剔除那些在摄像机视锥内但被挡住的对象,从而节约 GPU 渲染性能。

遮挡剔除的使用

总体思路

  1. 设置需要使用遮挡剔除的对象为遮挡静态对象
    • 会遮挡别人的物体(比如建筑、墙体、山体等)→ 设置为 Occluder Static(静态遮挡物)。
    • 可能被遮挡的物体(比如角色、家具、树木等)→ 设置为 Occludee Static(静态被遮挡物)。
    • 注意:动态物体不能作为静态遮挡物(Occluder Static)。
  2. 打开遮挡剔除窗口Window → Rendering → Occlusion Culling,在该窗口中进行遮挡数据烘焙。
  3. 摄像机需要开启遮挡剔除功能

场景搭建与设置

创建一个墙和一堆被遮挡物,设置为遮挡物和被遮挡物。

打开 Occlusion Culling 窗口,在窗口内也可以设置遮挡物和被遮挡物。

窗口参数

Occlusion Area(遮挡区域): 是一个体积框(Box Volume),用来限定在哪些区域里启用遮挡剔除计算。可以创建一个”盒子”空间,只有在这个区域内才会启用遮挡剔除计算。

它的作用是用于优化性能。如果场景很大、到处都做遮挡剔除,计算量很大,反而可能拖慢性能。加上 Occlusion Area 后,Unity 只在该区域范围内进行遮挡计算,可以用于精确控制在哪里启用遮挡剔除,比如只想在室内(走廊、房间)启用遮挡剔除,而室外空旷区域不需要。

注意:

  1. 它主要影响静态几何的遮挡剔除。
  2. 可以创建多个 Occlusion Area,把不同场景分开管理。

点击后可以看到会出现一个体积框 GameObject,可以设置它的位置和宽高,在这个体积框区域里启用遮挡剔除计算。

Smallest Occluder(最小遮挡物): 小于该尺寸的物体不会被当作遮挡者。太小的物体(比如椅子腿、路灯杆)即使当作遮挡者,对整体遮挡效果意义不大,反而增加计算复杂度。比如如果设为 5,那么宽高深任意方向小于 5 个单位的物体,不会被烘焙进”遮挡源”。

建议:

  • 大场景(城市/山体)→ 数值设大(比如 5~10)。
  • 小场景(室内/走廊)→ 数值设小(比如 1~2)。

Smallest Hole(最小孔洞): 小于该尺寸的孔洞会被”填上”,不会算作能透过去的空间。避免一些小缝隙(比如窗框、门缝)被计算成”可见路径”,导致不合理的可见性判断。比如如果设为 0.25,那么小于 0.25 单位的洞(例如小裂缝)会被忽略,当成墙壁。

建议:

  • 室内场景 → 设小一些,保证窗户、门洞能算作可见。
  • 城市/森林 → 设大一些,忽略不重要的小缝隙。

Backface Threshold(背面阈值): 决定一个物体有多少背面可以参与遮挡。遮挡计算时,通常只考虑物体面向摄像机的正面,但有些情况下,背面(比如反向法线)也能阻挡视线。数值范围为 0~100%,0 表示完全不考虑背面,100 表示所有背面都能参与遮挡。

建议:默认值就够用,除非场景特殊(比如很多单面平面作为墙)。

烘焙与验证

设置好后点击下方的 Bake 按钮,蓝色框代表烘焙区域。

点击烘焙后发现 DrawCall 次数没有下降,可能是因为摄像机没有进入遮挡的区域。

当选中 Visualization(可视化)页签,再选择开启遮挡剔除的摄像机时,可以实时地看到遮挡剔除效果。

摄像机进入区域后,点击 Visualization 页签可以看到被剔除的对象看不见了,摄像机没进入区域就能看见。

注意要检查摄像机有没有开启遮挡剔除。


74.2 知识点代码

Lesson74_性能优化_GPU_增强渲染性能_遮挡剔除.cs

public class Lesson74_性能优化_GPU_增强渲染性能_遮挡剔除
{
    #region 知识点一 遮挡剔除的作用

    //Unity默认只会进行视锥剔除
    //即 摄像机视锥外的物体不会渲染
    //但是在视锥内,被其它物体挡住的东西仍然会被渲染
    //而遮挡剔除就是用来弥补这一点的

    //遮挡剔除(Occlusion Culling)的作用
    //1.让 被遮挡、不可见的物体 不再进入渲染管线
    //2.减少 Draw Call、顶点处理、像素填充 等开销
    //3.提升性能,尤其是在 室内场景、城市场景、森林 这种遮挡很多的环境

    //比如:
    //玩家在一个房间里,外面的街道模型其实完全看不到,没有必要渲染它们
    //如果没有遮挡剔除,这些在摄像机视锥范围内对象依然会送进GPU渲染,浪费性能

    //说人话:
    //遮挡剔除弥补了视锥剔除的局限性
    //让Unity可以剔除那些在摄像机视锥内,但是被挡住的对象
    //这样可以节约GPU渲染性能

    #endregion

    #region 知识点二 遮挡剔除的使用

    //总体思路:
    //1.设置需要使用遮挡剔除的对象为遮挡静态对象
    //  会遮挡别人的物体(比如建筑、墙体、山体等)→ 设置为 Occluder Static(静态遮挡物)
    //  可能被遮挡的物体(比如角色、家具、树木等)→ 设置为 Occludee Static(静态被遮挡物)
    //  注意:
    //  动态物体不能作为静态遮挡物(Occluder Static)

    //2.打开遮挡剔除(Occlusion Culling)窗口
    //  Window -> Rendering -> Occlusion Culling
    //  在该窗口中进行遮挡数据烘焙

    //3.摄像机需要开启遮挡剔除功能

    //Occlusion Culling 窗口参数:
    //Occlusion Area(遮挡区域):
    //  是一个体积框(Box Volume),用来限定在哪些区域里启用遮挡剔除计算
    //  如果场景很大,到处都做遮挡剔除,计算量很大,反而可能拖慢性能
    //  加上 Occlusion Area 后,Unity 只在该区域范围内进行遮挡计算
    //  注意:
    //  1.它主要影响静态几何的遮挡剔除
    //  2.可以创建多个 Occlusion Area,把不同场景分开管理

    //Smallest Occluder(最小遮挡物):
    //  小于该尺寸的物体不会被当作遮挡者
    //  大场景(城市/山体)→ 数值设大(比如 5~10)
    //  小场景(室内/走廊)→ 数值设小(比如 1~2)

    //Smallest Hole(最小孔洞):
    //  小于该尺寸的孔洞会被"填上",不会算作能透过去的空间
    //  室内场景 → 设小一些,保证窗户、门洞能算作可见
    //  城市/森林 → 设大一些,忽略不重要的小缝隙

    //Backface Threshold(背面阈值):
    //  决定一个物体有多少背面可以参与遮挡
    //  数值范围:0~100%
    //  0 → 完全不考虑背面;100 → 所有背面都能参与遮挡
    //  默认值就够用,除非场景特殊

    #endregion
}


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏