文章目录

  • 剔除
    • 视锥体frustum裁剪
    • 遮挡剔除
    • 摄像机距离剔除
  • 遮挡剔除 Occlusion Culling
    • 建立遮挡剔除
    • 遮挡剔除窗口
    • 遮挡剔除烘焙 - bake
    • Occlusion Area 裁剪区域
    • 测试效果

剔除

提升代码效率的最佳办法,就是不执行它。提升渲染效率最佳的办法,就是不渲染它。

所以Unity提供了多种将对象从渲染列表中剔除的方法。

视锥体frustum裁剪

利用场景管理算法(2D用4叉树,3D用8叉树),快速收集在摄像机视锥体内的对象,作为潜在可见集。该算法的时间开销比较大,但是无法避免。但是,如果我们在场景中有镜子,水面等,希望反射的对象,则需要为这些对象建立反射摄像机,也要进行昂贵的裁剪。当然为了解决这个问题,Unity为我们提供了Reflection Probe来离线计算静态反射数据。

视锥体裁剪是自动的,不需要我们参与。

遮挡剔除

对于进入摄像机视锥体的对象,不一定能在视口看到它,比如一堵墙后的雕像,即使雕像在视锥体内,最终也会被墙挡住,所以渲染它是浪费。Unity提供了遮挡剔除,来解决该问题。将场景拆分成许多小的单元格子,一种用来表示渲染格子(Target Cells),用来容纳可渲染对象,一种表示摄像机格子(View Cells),用来定义摄像机可能到达的区域,然后离线的,建立View Cells和Target Cells之间的关系,将每个View Cell可见的 Target Cells存储起来,运行时直接查询收集可渲染对象。

摄像机距离剔除

摄像机距离剔除,是为每个Layer定义摄像机可见距离,渲染每个Layer的对象时,查询摄像机针对该Layer的渲染距离,超出该距离,就不渲染了。

该方式适用于场景中的装饰物体,如地上的小石头,草,各种Decoration对象。

启用该功能很简单,为摄像机设置相关值就行了:

Camera camera = GetComponent<Camera>();
float[] distances = new float[32];
distances[LayerMask.NameToLayer("Npc")] = 11;        //每一层的剔除距离
camera.layerCullDistances = distances;
//好处:在相机转动时,不会影响哪些对象可见或不可见,也就是不会转动中,有些原来显示的对象被隐藏
camera.layerCullSpherical = true;

遮挡剔除 Occlusion Culling

遮挡剔除用于在渲染时,剔除对被其它对象遮挡,摄像机无法观察到的对象的渲染。由于很多时候,距离摄像机远的对象先被渲染,近的后渲染时就会在远的上渲染,这导致一个像素被绘制多次,而且之前的很多次,实际上都是不可见的,这就叫overdraw。

下图展示了没有frustum裁剪时,渲染了所有的对象:

第二幅图展示了视锥体裁剪后,被渲染的对象少了很多:

第三幅图,使用遮挡剔除后,只有被摄像机看到的对象渲染,少了很多

遮挡剔除的处理过程,是用一个虚拟的摄像机遍历场景,建立潜在可见对象集合的层级关系。运行时摄像机利用这些数据标识哪些对象可见,哪些不可见。利用这些数据,Unity可以确保仅将可见的对象送入渲染管线,降低DrawCall,提升效率。

遮挡数据由一些单元格组成,每个单元格是整个场景的包围体的细分,这些单元格构建成一颗二叉树。遮挡剔除用了2棵树,一棵是View Cells(静态对象),和一棵Target Cells(移动对象)。View Cells映射到定义可见静态对象的索引列表,从而为静态对象提供更精确的筛选结果。

创建对象时,需要在对象的尺寸和Cell的尺寸间取得一个好的平衡点。不能定义相对于对象太小的Cell,也不应该创建覆盖太多Cells的对象。有时,将一些大的对象拆分成小对象,可以提升裁剪效果。同样的,可以将一些小的在同一个Cell里的对象合并来降低DrawCall。

可以在Scene视图中选择"OverDraw"渲染模式来查看OverDraw,在Game视图的Stats信息面板中查看总的渲染三角形数量,以及渲染批次。下面2张图,对比了是否开启遮挡剔除的效果及数据

该图未开启遮挡剔除,注意Scene视图中的OverDraw,墙后面的大量的房间的渲染,造成了较高的OverDraw,这些房间在游戏视图中是看不到的。

应用遮挡剔除后,远处的房间不再渲染,OverDraw也低了很多。绘制的三角形数量和渲染批次也显著降低了。

建立遮挡剔除

首先,将关卡打散到合适的尺寸,这样有利于高效地被那些大的对象遮挡住,以剔除,如墙,大的建筑。例如如果一个房间里有很多家具,这些家具应该各自进行剔除,而不是合并到一起,虽然合并到一起降低了drawcall。

为了让对象参与遮挡剔除,需要将对象的tag设置为Occluder Static或者Occludee Static。可以选择多个对象一次进行设置。

Occludee Static:那些小的,会被其它对象挡住的对象,设置为 Occludee Static。

Occluder Static:大的物体,会遮挡其它对象的对象,设置为 Occluder Static 。

当使用了LOD group时,只有LOD0的对象会被当做遮挡对象。

遮挡剔除窗口

从 Window>Rendering>Occlusion Culling 打开遮挡剔除窗口。

在该窗口,可以处理遮挡Mesh和遮挡区域。

在Object面板,如果在场景里选择了Mesh,可以修改它们的遮挡类型:遮挡或者被遮挡,或者2者都设置

如果时选择了遮挡区域(Occlusion Area),则可以设置遮挡区域属性

注意:如果没有创建裁剪区域,那么裁剪将会被应用到整个场景。

注意:一旦摄像机不在裁剪区域内,遮挡剔除将会失效,所以设置遮挡区域完全覆盖摄像机的可达区域非常重要。但是过大的裁剪区域也需要更长的数据烘焙时间。

遮挡剔除烘焙 - bake

set default parameters 按钮,重置参数为Unity默认参数,以适应大多数情况。当然可以调整参数,适应我们的场景。

参数 含义
Smallest Occluder 执行遮挡剔除时,会遮挡其他对象的对象的最小尺寸。小于改尺寸将不会遮挡其它对象。选择一个合适的值来平衡裁剪精度和裁剪数据尺寸。
Smallest Hole 该值表示摄像机视线能穿过的,2个几何体之间的最小距离。该值表示能通过该孔的对象的直径。
Backface Threshold Unity通过背面测试来减少不必要的细节,来优化遮挡数据。默认值100非常简单地,不从数据集合中移除背面。将参数设置为5,可以根据可见背面的位置,大大降低数据量。例如,当摄像机在地形下面,或者实体对象内部,这些摄像机不会到达的区域。距离背面大于该参数的位置将不会生成遮挡数据。

Occlusion Culling - Visualization

窗口最下方,时Clear和Bake按钮。点击Bake按钮,开始生成遮挡数据。生成后,可以切到 Visualization面板,预览测试遮挡剔除。如果觉得结果不满意,点击Clear按钮,清除数据,然后调整参数,再重新烘焙。

场景中的所有对象都会影响包围体的大小,所以要尽量让它们都在场景的可见范围内。

烘焙完成后,可以看到蓝色的立方体,每个立方体是一个裁剪区域。

Occlusion Area 裁剪区域

为了对移动对象进行遮挡,需要创建 Occlusion Area ,并修改它的尺寸来适应移动对象能到达的区域。可以为一个空的对象添加 Occlusion Area 组件来创建。

创建完后,选择 Is View Volume 来遮挡移动对象。(移动对象与摄像机不在同一个遮挡区域内,不可见?)

创建完遮挡区域后,需要查看是如何将盒子拆分到Cells中的。要看遮挡区域是如何计算的,在 Occlusion Culling Preview Panel 中,选择 Edit,并选中View Volumes复选框。

测试效果

设置好遮挡后,可以在 Occlusion Culling Preview Panel 的 Visualize mode 中,选中 Occlusion Culling,在Scene窗口中移动摄像机来进行测试。

当移动摄像机时(无论是否在play模式),会看到一些对象被禁掉了。在这里,可以查找遮挡数据的错误。当你移动摄像机时,看到一个对象突然跳出来,说明有错误发生。当发生这种情况,可以改变分辨率,或者调整对象位置来解决。可以将摄像机移动到出问题的对象处,进一步检查问题。

数据生成后,视图中会有一些带颜色的立方体。蓝色的表示Target Volume(被遮挡对象)的Cell划分,白色的是View Volume(摄像机位置包围框)的Cell划分。如果参数设置正确,可以看到一些对象不被渲染,可能不在视锥体内,也可能是被遮挡剔除掉了。

如果你发现场景中没有任何对象被遮挡,那么打碎你的对象,让这些碎片完全包含在一个Cell内。

Culling 渲染剔除相关推荐

  1. Occlusion Culling 遮挡剔除 相机系列5

    Occlusion Culling 遮挡剔除 本文档主要是对Unity官方手册的个人理解与总结(其实以翻译记录为主:>) 仅作为个人学习使用,不得作为商业用途,欢迎转载,并请注明出处. 文章中涉 ...

  2. UE4-LOD理解-Distance culling(距离剔除体积)和Visibility culling(可视化剔除体积)

    Distance culling 和 Visibility culling 本篇只是知识点备注 Distance culling Visibility culling 本篇只是知识点备注 Distan ...

  3. Unity Occlusion Culling 遮挡剔除研究

    本文章由cartzhang编写,转载请注明出处. 所有权利保留.  文章链接:http://blog.csdn.net/cartzhang/article/details/52684127  作者:c ...

  4. OpenGL Indirect Culling间接剔除实例

    OpenGL 间接剔除实例 先上图,再解答. 完整主要的源代码 源代码剖析 先上图,再解答. 完整主要的源代码 #include <shader.h> #include <objec ...

  5. OpenGL 面剔除Face culling

    OpenGL面剔除Face culling 面剔除Face culling简介 环绕顺序 面剔除 面剔除Face culling简介 尝试在脑子中想象一个3D立方体,数数你从任意方向最多能同时看到几个 ...

  6. DirectX12 - Triangle Culling and Winding Order(三角形的剔除与绕序)

    这里是SunshineBooming,GPU公司一枚小小的Driver工程师,主要工作是写DirectX12 Driver,我会持续更新这个DX12 Spec系列,可能比较冷门,但是都是干货和工作中的 ...

  7. Unity 3D 遮挡剔除(仅专业版) Occlusion Culling (Pro only)

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! Occl ...

  8. Unity Shader - ShaderLab: Culling Depth Testing 剔除与深度测试

    目录:Unity Shader - 知识点目录(先占位,后续持续更新) 原文:ShaderLab: Culling & Depth Testing 版本:2019.1 ShaderLab: C ...

  9. 【逆向】UE4 渲染流程分析

    UE4作为当今商业引擎界的大佬,渲染和图形质量一直是首屈一指的水准,但是相对于unity来说UE4基本上是一套完整方案提供,不通过源码修改对渲染进行定制的可能性比较小,而且同时UE4这方面的文档很少, ...

最新文章

  1. Illustrator+FontLab 进行字体设计教程
  2. 如何使用代码创建和读取 SAP CRM 订单的 Text 数据
  3. 通信PK电子,谁牛?
  4. 变化的你--写给宝宝
  5. python真是最烂的语言_在大型项目上,Python 是个烂语言吗?
  6. linux 系统终端字体改变,linux系统终端修改字体的方法
  7. 在B/S开发中经常用到的javaScript技术(转载)
  8. ajax调用网易云APi遇到跨域问题
  9. 测控专业英语复习资料
  10. Python3自然语言处理(2)——获得文本语料库和词汇资源
  11. Java中如何保证线程安全
  12. 【数据结构】栈的应用--括号匹配的检验
  13. 计算机考试多少个小时,考驾照科一电脑刷几个小时
  14. STM32F4定时器介绍
  15. 面板数据分析及stata应用笔记
  16. 如何“避雷”(化解风险)
  17. 【C语言零基础教学】——入门篇
  18. 理财入门之萌萌赚钱观
  19. 一、(4) 结巴分词词性提取
  20. 汽车音响AMP功放-扬声器诊断驱动开发

热门文章

  1. iText5使用绝对定位制作pdf打印针式发票,支持跳页
  2. 金蝶服务器连接协议,金蝶kis客户端连接主机服务器
  3. 首批5G手机过万元,购买5G手机的合适时间或在2020年后
  4. java链表并集_求链表的并集和交集
  5. Java求交集、并集、差集
  6. PPT转换PDF怎么做?
  7. GLES3.0中文API-glGetActiveUniform详解
  8. 重庆邮电大学计算机考研录取名单,重庆邮电大学2019年硕士研究生复试拟录取名单公示(第一批)...
  9. 多关键字排序问题-瑞神打牌
  10. 【浙大版《Python 程序设计》题目集(解)】第3章-1 大于身高的平均值(10分)