Unity --- InstantOC(渲染管线,遮挡剔除与LOD)

Posted Metallic Cat

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity --- InstantOC(渲染管线,遮挡剔除与LOD)相关的知识,希望对你有一定的参考价值。

第一部分 --- InstantOC(渲染管线,遮挡剔除与LOD)

 

1.渲染管线通俗的讲就是为了使内存中的数据变为屏幕上的图像,我们所做的一系列操作

这个图的分界线上方都是GPU做的操作,下方则是GPU做的操作

1.CPU做的操作:

a.判断处于摄像机的视锥以内的那些游戏物体需要进行渲染和显示

b.判断完之后调用图形API接口,并将要渲染的游戏物体的数据作为输入传给接口,接口在接收到数据后就会在对数据进行了一定处理后将数据输入到GPU中,让GPU渲染图像,渲染完毕之后就会输出图像,输出的图像会存到缓存中 --- 如果是WINdows系统的话,调用dirtX接口,如果还是移动端的话调用openGL接口

绘制调用Draw Call是一个参数,这个参数反映的是在一帧的时间里,通过渲染管线渲染游戏对象的次数

在一帧的时间里出现了10个游戏物体的话(无光照),那么我们就要调用10次渲染管线进行渲染,此时的draw call为10

draw call 越大,GPU的渲染压力越大,需要的渲染时间越长,所以draw call越小越好

1.查看draw call的方法 --- 在游戏界面处点击state(状态),然后在graphics处的Batches旁就能看到当前draw call数

在没有光照的情况下,每增加一个游戏物体draw call就会 +1 ,而在有光照的情况下,每增加一个游戏物体draw call就不是简单的 +1 了,由于光照条件下的游戏物体的渲染非常复杂,往往需要走多次渲染管线后才能够将游戏物体渲染成功,所以每在光照环境下增加一个游戏物体,其draw call就会增加大于1的值

1.CPU负责识别要渲染的游戏对象,以及这些对象的相关图形数据(比如游戏模型的顶点坐标(每一个三角形面的三个顶点的坐标),三角形个数等等)

2.GPU在接收到CPU发来的数据之后就会开始渲染出对应的图像

1.这个坐标系转换是将顶点的3维坐标转换为显示在屏幕上的对应位置的二维坐标

1.光栅化就是在计算图元装配后得到的每个小三角形在屏幕上所占的像素总数

 1.给定一个小三角形,这个三角形在屏幕上占据的像素个数在光栅化的过程中已经确定好了,接下来给属于小三角形的每一像素上色的过程称为像素处理

1.当两个游戏物体发生重合的时候,GPU怎么知道到底该渲染那一个游戏物体的图像到屏幕上的呢? --- 这个显示的顺序就是由深度信息决定的,深度越大,在图层中的位置就越高,显示时的优先级越高

而存储深度信息的内存块就别称为深度缓存

2.GPU显示的画面都是从帧缓存中读取的,读取的频率是一帧读取一次

1.draw call越小,渲染图像所需的时间越短,游戏运行的就更流畅,那么我们该如何降低draw call呢? --- 第一个介绍的技术就是 instant occulusion culling (即时遮挡剔除) --- 将被遮挡的游戏物体剔除,不进行渲染,减少draw call

2.Unity提供的是静态遮挡剔除,也就是说Unity提供剔除功能能够处理的只有我们在运行游戏前已经布置好的游戏物体,在运行游戏时通过代码添加的新的游戏物体是无法进行遮挡剔除处理的

因此为了解决这个问题,我们可以安装一个即时遮挡剔除插件来代替Unity的静态遮挡剔除功能帮我们处理游戏物体

 1.安装InstantOC插件,然后将其导入到Unity中

1.导入插件后可能会出现这样一个提示框,出现这个原因是我们导入的插件中的代码段里使用的某些方法是Unity旧版本的方法,此时我们的新版本已经废弃了这些旧方法并更新了新方法,如果我们想用这个插件的话,就必须把这个插件中的代码段里的旧方法也更新为新方法

此时更新有两种选项,一个是让Unity自动帮你更新(左边的选项),另一个就是自己手动更新(右边的选项)

1.导入的插件会在Project面板中出现

2.Readme文件翻译过来就是 自述文件,相当于使用说明书

1.这个C#脚本是非常重要的一个脚本:cam就是camara的缩写,这样命名的用义就是说明这个脚本是用在camara摄像机上的

1.第一个参数是层 --- 此处我们要选择的是需要参与遮挡剔除的层,第二个参数是标签 --- 选择的是需要参与遮挡剔除的游戏物体的标签

2.第二个参数是采样Samples,介绍这个参数的时候需要先介绍一下即时遮挡剔除的原理:

即时遮挡剔除插件会通过代码使得以摄像机为原点,摄像机对应的视锥为范围,不断的射出看不见的射线,让这些射线与游戏物体做碰撞检测(无法穿透),检测成功的游戏物体(发生碰撞)就进行渲染和显示,检测失败的游戏物体(没发生碰撞)就不进行渲染和显示(不进行渲染的方式就是通过代码关闭这个游戏物体的mesh render组件)

发射射线的时间间隔是一帧

而这个Samples采样参数就是在设置每一次发射射线的时候,我们要发射出多少根射线(控制射线发出以及进行碰撞检测判断的是CPU,CPU承接了这个功能的计算负担)

(优化的原则是将GPU的负担转移到CPU上)

1.射线视野就是指射线能够偏转的角度的范围,这个数值参照的是摄像机组件中的FOV视野范围角度(要求是大于等于)

2.射线长度参照的是我们在摄像机组件中设置的最远观察范围Far(超过最远观察范围的我们都看不见,那也就没必要射到那里去了)

3.第三个参数Hide Delay应该翻译为隐藏延迟,首先如果只通过一帧发射几百根射线就判断一个物体是否被遮挡是不现实的(很可能会出现遗漏的情况),为了避免遗漏我们多发射几次射线,多进行几次检测后再进行遮挡剔除以此来提高准确性,我们设置的这个次数就是所谓的隐藏延迟参数

(实时阴影一般不点,没有什么用)

1.在进行射线的碰撞检测前我们需要为游戏物体添加碰撞体组件 --- box colider(绿框框)

2.场景中会出现了大量被遮挡的游戏物体的时候才用遮挡剔除,不要什么时候都用,不然的话会出现CPU的工作量白白增加了却没有什么效果

3.只有被完全遮挡的物体才会被剔除

1.多细节层次翻译过来就是突出重点,忽略非重点  --- 靠近摄像机的游戏物体用高细节层次进行渲染,远离摄像机的游戏物体用低细节层次进行渲染

2.一个游戏物体的模型面数越多,这个游戏物体就越逼真,同时渲染这个游戏物体所需的时间就越长(顶点数越多,CPU需要处理的顶点数据就越多)

1.Baches就是draw call -- 是一帧需要进行渲染显示的游戏物体个数

Tris则是需要渲染的总三角面数,Vets则是所有模型的顶点数之和 

2.注意游戏资源的参数一改变就会导致根据这个资源创建的所有游戏物体对应的参数跟着改变

而改变一个游戏物体的参数只会对这个游戏物体本身造成影响

1.当游戏物体和摄像机之间的距离小于LOD 1 distance的话,就会显示精模,大于 LOD 1 distance 小于 LOD 2 distance的话显示中模,大于LOD 2 distance 显示简模

2.InstancOC规定,精模只能用LOD_0命名,中模用LOD_1,简模用LOD_2,不然的话这个插件它无法识别对应的模型文件

3.这里LOD的原理就是检测模型和摄像机之间的距离,然后查找对应的模型进行显示、

4.这个技术最大的缺点就是需要的内存空间大,因为我们需要同时在内存中存储高,中,低三种模型来满足不同距离下的显示

其次CPU还需要承担距离判断的计算任务

5.LOD技术的使用条件:场景中存在高面模型,且这个高面模型会发生移动

右键点击后profiler(分析器)就能够调出一个数据面板

这个面板中实时记录了CPU,渲染和内存的工作状况,以后进行优化的时候就可以根据这个面板中的工作状况来进行针对性优化

Unity3D之InstantOC(遮挡剔除)

首先要先从网上下载InstantOC组件(网上资源很多的不用跟我要)

那么介绍一下这个组件是干什么用的,为什么要用它,有什么好处

在游戏中我们看到的物体,是如何呈现给我们的呢?如图:

渲染管线

技术分享图片

 

CPU干得事情

第一步 游戏:其实就是CPU来判断视锥以内,所能看到的物体都需要渲染

第二步 图形API:它是要看你发布的平台,不一样平台所需要的图形API也就不一样,比如Windows平台就需要DX,手机端平台就需要OpenGL等。。。。

第三步:绘制调用Draw Call每次引擎准备数据并通知GPU的过程,其实就是说每帧调用显卡渲染物体的次数(CPU与GPU的分界线)

 

GPU干得事情

第四步 顶点处理:接受CPU传输过来的顶点数据,来坐标转换(模型都是有若干个点和三角构成的)

第五步 图源装配(组装面):连接相邻的顶贴,绘制位三角形

第六步 光栅化:计算三角形的像素,并为后面着色阶段提供合理的插入参数

第七步 像素处理:对每个像素区进行着色,并写入到缓存中

第八步 缓存:一个存储像素数据的内存块,最重要的缓存是帧缓存和深度缓存

    帧缓存:存储每个像素的色彩,即渲染后的图像,帧缓存常常子啊显存中,显卡不断读取并输出到屏幕中

    深度缓存:Z-buffer:存储像素的深度信息,即物体到摄像机的距离,光栅化时变计算各像素的深度值,如果新的深度值比现有值更近,则像素颜色被写到帧缓存,并替换深度缓存 

 

  通过上面的叙述知道了游戏物体在渲染中是需要CPU和GPU共同来完成,那么在这个过程中一旦数据量变大一定回造成电脑性能上的消耗,为了降低消耗所以要使用InstantOC这个组件。

  那么来介绍一下InstantOC,InstantOC全称叫做Instant Occlusion Culling(遮挡剔除),为什么要用它?因为在摄像机的视锥内也有被物体所被遮挡而看不见的物体如果一起渲染出来会浪费大量的性能!因此我们就可以用遮挡剔除来减少GPU的工作量但同时也会增加CPU的工作量,那么如果在物体少或者没有遮挡的情况下就不要使用了(遮挡剔除)因为如果所有物体都需要渲染的话那再使用遮挡剔除无疑是给CPU增加了负担,那么遮挡剔除总结:当物体被送进渲染流水线之前,将摄像机视角内看不到的物体进行剔除,从而减少每帧渲染的数据量,提高了渲染性能,介绍了这些那就开始介绍它如何使用吧!

第一步:从网上下载一个InstantOC就是一个工具包,然后导入到Unity3D里(什么你问我怎么导入?,直接拖进去就可以了)!

第二步:导入完成后可以在Unity3D面板中看到一个名称叫做InstantOC文件夹,在这个文件中有一个IOCcam的C#脚本将它导入值摄像机(导入步骤也是托进去)

技术分享图片

第三步:将导进摄像里的IOCcam脚本来进行参数配置,在所需要遮挡剔除的物体上的Layer(层)和Tag(标签)添加一个自定义的名称 ,分别给Layer mask(遮罩层)和 IOC Tag(遮挡标签)进行绑定

然后还需要设置Samples(取样)其实就是摄像机向视锥以内的物体发射一些射线碰到了就渲染碰不到就不渲染(射线是看不到的)

那么这些射线是随机发射的如果场景太大射线少就会导致物体明明能看到因为射线的原因没有碰到导致没有去渲染,

或者射线太多导致性能降低所以在射线这里是有一个规范的射线数量一般会设置在150-500之间

Rays FOV 射线远视:应大于摄像机视野Fied of View

View Disance:视图距离,射线长度将影响摄像机Clipping Planes——Far 数值

Hide Delay延迟隐藏,当物体被剔除是延迟的帧数,建议50-100之间(就是多让射线,多试几次毕竟射线是随机的所以需要延迟隐藏那些看不到的物体)

PreCull Delay:这个一定要勾选

技术分享图片技术分享图片

那么在介绍一个这个组件上另外一个功能LOD!LOD全场叫Levels of Detail(多细节层次)LOD技术指根据物体模型的节点在显示环境中所处的位置和重要度,决定物体渲染的资源分配,降低非重要物体的面数和细节度,从而获得高效率的渲染运算

其实就是说当物体距离远了的时候才用面数较低的模型来减少渲染运算的工作量,来保证性能的一步优化

来开始如何使用它吧

使用方法:还是刚刚的步骤不变,在图下有这么几个属性需要设置一下,分别是Lod 1 distance和Lod 2 distance这是指摄像机与模型之前的距离 1代表精模(面数比较高的模型)2代表中模(代码面数一般的模型)如果超出这连个所设置的距离则会变成低模(面数比较低的模型),那么把数值调整好了 模型怎么办呢?(不用担心,工具本身是自带这3个模型的)如图 ,那么这里要说明一下 LOD是有命名规则的模型名称一定叫Lod_0、Lod_1、Lod_2来区分模型的面数如图,记得放到同一个空物体里,最后一张是配置完成后的

 技术分享图片技术分享图片技术分享图片技术分享图片

 

以上是关于Unity --- InstantOC(渲染管线,遮挡剔除与LOD)的主要内容,如果未能解决你的问题,请参考以下文章

使用InstantOC实现动态遮挡剔除 + LOD效果

Unity3D之InstantOC(遮挡剔除)

使用InstantOC实现动态遮挡剔除 + LOD效果

Unity渲染工作原理--和instantOC插(减少CPU 和 GPU的工作量)

Unity学习笔记4:遮挡剔除LODProfiler光照声音

Unity学习笔记4:遮挡剔除LODProfiler光照声音