场景剔除--视锥剔除和硬件剔除

 

/

剔除算法综述

在游戏运行中,引擎渲染出数以万计的物体,场景复杂度往往是数千万面的级别,同时还需要处理千计盏灯光和数百种材质。因此,如何有效地减少不必要的绘制就显得格外重要。本文将就游戏引擎中用到的各种剔除技术进行概述,会较少涉及细节,感兴趣的同学可以去看文末的参考文献,文献中会有相关剔除算法的原理和具体实现。

我们将分为以下四个方面来介绍:

1.场景剔除工作原理

2.常用剔除算法

3.总结

4.参考文献

一、场景剔除工作原理

对于场景物体的剔除一般分为可见性剔除和遮挡剔除:

1.可见性剔除

可见性剔除通过判断物体与相机的距离(距离剔除)或者是否在相机的视锥体内(视锥体剔除)来对物体进行剔除。

如图所示,不在相机视锥体内部的物体将被剔除不进行渲染。

2.遮挡剔除

遮挡剔除则是在相机可见范围内通过判断物体是否被其他物体遮挡来对物体进行剔除。遮挡剔除有基于整个物体是否被遮挡的剔除(Hiz、硬件遮挡查询等),也有基于像素级别的遮挡查询(Early Z)。

图中蓝色虚线的物体被相机前方的物体遮挡,并将剔除不进行渲染。

二、常用剔除算法

本文将大致介绍以下剔除算法的原理和实现过程:

(1).距离剔除

(2).视锥体剔除

(3).Occluder剔除(软件剔除)

(4).视口剔除

(5).背面剔除

(6).遮挡查询(Occlusion Query)

(7).Early Z Culling

(8).Hiz Culling

(9).PVS

1.距离剔除

剔除阶段:应用程序阶段。

通过物体和相机的距离进行判断物体是否被剔除,原理比较简单,剔除效率也相对较高。在UE4中可以通过物体属性设置剔除的最大距离和最小距离(如下图):

2.视锥体剔除

剔除阶段:应用程序阶段。

即简单的判断一个物体是否位于视锥棱台内。裁剪的依据主要是根据摄像机的视野(field of view)以及近裁减面和远裁剪面的距离,将可视范围外的物体排除出渲染。

上图中1为近裁剪屏幕,2为裁剪截面体,3为远裁剪平面

在实践中,由于模型往往是比较复杂的,很难精确计算它和视锥体的交集,因此一般是用轴对齐包围盒(AABB),有向包围盒(OBB)或者包围球(BSphere)代替模型本身进行相交计算。

视椎体剔除是减少渲染消耗的最有效手段之一,可以在不影响渲染效果的情况下大幅减少渲染涉及到的顶点数和面数。

3.occluder剔除(软件剔除)

剔除阶段:应用程序阶段。

这个方案的思路是,首先利用CPU构造一个低分辨率的Z-Buffer,在Z-Buffer上绘制一些场景中较大的遮挡体:

在构造好的Z-Buffer上,绘制小物体的包围盒,然后执行类似于occlusion query的操作,查询当前物体是否被遮挡:

由于是纯CPU的,集成起来也比较简单,同时不会有GPU stall的问题。缺点是需要美术指定一些大的遮挡体,对CPU性能有一定的消耗。在UE4中通过物体actor的LOD For Occluder设置遮挡体。

4.视口剔除

剔除阶段:投影变换之后屏幕映射之前。

发生在几何阶段(Geometry Stage)后期,投影变换之后屏幕映射之前,是渲染管线的必要一环。只有当图元完全或部分存在于规范立方体内部的时候,才将其返送到光栅化阶段。其中,对于完全位于规范立方体内部的图元,则直接进行下一阶段;完全处于规范立方外部的图元则完全被舍弃;部分处于规范立方体内部图元,则会根据视口进行对应的裁剪,在这一过程中可能会产生新的顶点。通过视口剔除可以将视口外的图元舍弃掉,减小光栅化阶段的消耗。

5.背面剔除

剔除阶段:在光栅化阶段进行。

当我们观察场景中对象时,一般只能以一定角度来观察,那么对象的某些面我们是看不到的,例如你观察一个立方体,最多只能同时看到3个面,有时只能看到1个面,而我们绘制时如果不采取剔除背面的措施,则要绘制6个面,其中包括一些我们根本看不到的面。对于立方体这个面较少的几何对象,性能开销不明显,但是对于复杂的模型,开启背面剔除则能明显改善渲染性能。 背面剔除,就是早点丢弃对观察者来说是背面的片元的一种方法。

剔除的基本原理是先判定多边形的朝向,并和当前的观察方向进行比较。opengl中设置背面剔除相关函数:

glFrontFace(GL_CW); 设置顺时针或者逆时针为正面

glCullFace(GL_BACK); 设置剔除正面或者背面

背面剔除在光栅化阶段进行,执行在Vertex Shader 之后,在Fragment Shader片元着色器之前。

6..遮挡查询(Occlusion Query)

剔除阶段:在深度测试时得到待剔除物体,在应用程序阶段执行。

参考步骤和代码:

https://developer.download.nvidia.cn/books/HTML/gpugems/gpugems_ch29.html

https://www.cnblogs.com/mazhenyu/p/5083026.html

简单来说,occlusion query允许你在绘制命令执行之前,向GPU插入一条查询,并且在绘制结束之后的某个时刻,从GPU将查询结果回读到系统内存里。这条查询命令得到的是某次DrawCall中通过Depth Test的Sample数量,当这个Sample的数量大于0时,就表示当前模型是部分可见的,否则当前模型完全被遮挡。

opengl中实现API接口:

//生成查询物体ID

glGenQueries(GLsizei n, GLuint *ids);

//开始遮挡查询

glBeginQuery(GL_SAMPLES_PASSED, 1);

//结束遮挡查询

glEndQuery(GL_SAMPLES_PASSED);

//根据Sample值param是否大于0判断查询号为id的物体是否被遮挡

glGetQueryObjectiv(GLenum id, GLenum pname, GLint *param);

对于复杂的场景,一个显而易见的优化策略就是用包围盒代替模型本身去做渲染,为了更加精确,我们也可以用多个紧贴的包围盒或者相对原模型更简单的Proxy Mesh去做occlusion query。基于这些API,我们就可以得到一个比较简单的遮挡剔除策略:

  1. 首先为这些物体生成查询对象ID 调用glGenQueries
  2. 调用glBeginQuery开始遮挡查询
  3. 渲染包围体
  4. 调用glEndQuery 结束遮挡查询
  5. 调用glGetQueryObjectiv,根据ID提取遮挡查询的结果,并根据结果绘制相应的物体。
  6. glDeleteQueries 删除ID,回收资源。

Occlusion query的另一个缺点(也是最致命的缺点)是,它需要将查询结果回读到系统内存里,这就意味着VRAM->System RAM的操作,走的是比较慢的PCI-E。

为了解决这个问题,比较常用的的方法是让CPU回读前一帧的occlusion query的结果,用来决定当前帧某个物体是否visible,对于相机运动较快的场景,用上一帧的结果可能会导致出错,但由于一般是用包围盒,本身就是保守的剔除,所以总体来说影响不明显,UE4默认使用的就是这样的遮挡剔除方案

7.Early Z Culling

剔除阶段:在光栅化阶段后,片元shader执行前。

我们知道传统的渲染管线中,深度测试是发生在Pixel/Fragment Shader之后的但是,如果我们仔细想下,在光栅化的时候我们已经知道了每个片断(fragment)的深度,如果这个时候我们可以提前做测试就可以避免后面复杂的Pixel/Fragment Shader计算过程。

提到Early-Z就必须提对应的Late-Z:在图形管线中,逻辑上Depth Test和Stencil Test是发生在Pixel Shader的执行之后的,因为Pixel Depth在Pixel Shader阶段还有可能被修改,所以Pixel Shader->Depth Test的流程顺序就是Late-Z。但由于Pixel Depth修改的需求非常少(基于深度混合的Impostor和某些粒子效果),所以绝大部分情况下,Pixel Depth在Rasterization之后、Pixel Shader执行之前就可以被确定下来,如果我们能够把Depth Test放在Pixel Shader之前,对那些没通过Depth Test的像素不执行Pixel Shader,就能够一定程度上减少SM的压力,这就是Early-Z这个优化策略的初衷,现在已经是GPU的标配了。默认在Pixel Shader里没有修改Depth的操作时,这个优化就会开启。

UE4在Prepass中生成earlyZ Depth,然后在光栅化后执行EarlyZ Culling

8.Hiz Culling

剔除阶段:在几何shader得到待剔除物体,在顶点shader执行。

参考步骤和代码:

https://github.com/nvpro-samples/gl_occlusion_culling

Hiz Culling同样是基于GPU但不同于EarlyZ Culling的剔除算法,Hiz Culling使用几何着色器先生成对应物体的包围盒,然后根据物体的包围盒选择对应层级的depth map。利用depth map 对应像素值对包围盒进行剔除,得到物体可见性并作标记。为了避免GPU返回标记到内存而造成时间消耗,通常使用Transform feedback将此数据流式传回到顶点shader中,也就是常使用的2-pass。

具体算法过程如下:

(1)拿到上一帧场景深度buffer,利用深度buffer构造分层深度图像,我们将其称为Hi-Z map。这些分层的深度图是对深度缓冲区进行mip-map得到,其中mip级别i中的每个像素包含mip级别i-1中的对应像素块的最大深度。

(2)将当前待绘制的场景物体分为两个集合:集合1.上一帧已有的物体集合(这里不一定和上一帧已有物体数量相同,有可能上一帧在相机可视范围而当前帧不在等情况)。集合2.当前帧新增的待渲染物体

(3)处理集合1:在构建Hi-Z map后,根据集合1物体的包围盒大小取对应级别的Hi-Z map深度图,并通过比较物体的包围盒深度值和存储在对应深度图深度信息来执行遮挡剔除,通常我们比较包围盒六个顶点深度值与对应位置周围的四个像素的深度值判断物体是否被遮挡。

(4)根据(3)剔除的结果绘制集合1,更新深度buffer

(5)处理集合2:利用新的深度buffer建立mipmap深度图,对集合2进行剔除。

(6)绘制集合2中物体,更新深度buffer。

值得注意的是:我们对剔除的判断是在几何shader中进行,完成物体可见性判断后,利用transform feedback 将可见性数据流传回到顶点shader中,这样可以避免数据从GPU写回到内存。

9.PVS

剔除阶段:应用程序阶段。

像其他剔除方法一样,预计算可视性体积用于实现中小型场景的性能优化,通常用于因为硬件问题而使动态遮挡剔除受到限制的移动平台。预计算可视性体积根据玩家或摄像机的位置,将Actor位置的可视性状态存储在场景中。

由于预计算可视性是在线下生成的,因此可以省去用于硬件遮挡查询的渲染线程时间,但代价是会增加运行时内存和照明构建时间。基于这一点,建议仅在玩家或摄像机可访问区域放置体积来保持可视性剔除。

  标准 PVS分为两步:

  1. 先求解简易模型:减面,枚举模型上每个顶点,找到一个点使得删除该顶点,模型变形最小,不停的寻找并删除影响最小的点直到模型变形超过一定阀值。最终求解出简易场景模型,为第二步计算做准备。

  2. 划分成小的三维格子,在格子里面均匀或随机选取 N个采样点做为摄像机位置,每个采样点 360度全方向做一定数量的射线出去,和场景中的模型判断交点,求解出该采样点的PVS,然后合并格子里N个采样点的结果为该格子的PVS。有离线计算好的,也有实时计算摄像机周围空间未计算格子的,等摄像机移动到那里时已经计算好了,无外乎精度不同。实际绘制时将所在格子的PVS提取出来再做一次视锥剔除就行。

三、总结

本文主要对当前引擎常用的一些剔除算法做了综述。剔除的本质是消耗少量的计算剔除尽可能多的物体,如果场景物体不复杂或者说互相遮挡不多,此时用一些计算复杂的剔除算法反而可能使帧率降低。因此,需要根据不同的情况选择合适的剔除方法,例如对于有大量植被实例场景可以考虑设置距离剔除,场景中有比较大的遮挡物则可以考虑occluder剔除,在手机平台我们可以考虑基于预计算剔除PVS等,通过这些剔除算法来提升游戏场景帧率。

/

视锥剔除和硬件剔除

视锥剔除

视锥剔除非常容易理解,其实就是只渲染能在视锥内看到的物体。

为了更加方便快速地实现视锥剔除、碰撞检测[1]等功能,通常我们会使用一些数据结构来管理场景中可见的物体。

空间数据结构

首先我们要选择一种 Bonuding Volume 来作为物体的边界,BV 可以是 AABB(axis-aligned bounding boxes)、OBB(oriented bounding boxes)、和Circle/Sphere。BV确定了一个物体的大致边界,在视锥剔除中,我们会直接使用BV进行检测。在碰撞检测时,我们先使用BV检测碰撞,再根据物体的真实边界进行判断。

三种常见的BV

最常见的三种场景物体组织数据结构是 Bounding Volume Hierarchical(BVH)、Axis-Aligned BSP Trees (k-D Trees)、Octree/Quadtree。

BVH将空间中的物体,使用树的方式来进行管理,下图是一个使用球形BV,构建出BVH的示例。BVH中,父节点的BV,是包含了所有子节点的BV的。在计算场景中物体的可见性时,我们从BVH的根节点开始遍历,就可以非常快速地遍历场景中所有物体的可见性信息。

视锥剔除,右边是管理场景中物体的BVH

BVH是将场景中的物体进行组织划分, k-D Trees则是将整个场景进行逐层次的空间划分,通常我们会使用AABB BV 来配合k-D Trees的实现:

k-D Tree

Octree/八叉树是 k-D Trees的一种特殊实现方式,所有的空间划分都是均匀分割的,这样使得实现更加简洁,不用考虑分割位置计算等问题。

八叉树

BV和视锥相交算法

1、视锥剔除的计算流程

已知我们场景中的物体都是使用空间数据结构+Bounding Volume 结构保存的,通常情况下,我们进行视锥剔除的大致流程如下:

遍历节点,对于每个父节点的 BV,和视锥 frustrum 进行一次相交测试,相交测试的结果有这样三种:不相交、相交、包含,这样的相交测试叫做 exclusion/inclusion/intersection test。因为测试相交和包含的计算量很大,有的时候我们会把算法简化,得到的结果为相交、不相交,这种相交测试叫做 exclusion/inclusion test。三种状态结果的相交测试,虽然会耗费额外的计算开销,但是允许我们直接跳过包含状态下整个父节点下的所有子节点的便利,因此一般认为三种状态的相交测试更好。

当测试结果是不相交,那么父节点下所有子节点的相交测试都可以直接跳过;当测试结果是包含,那么父节点下所有子节点都可以认为是相交的,子节点的相交测试也可以跳过;当测试结果为相交时,会继续遍历子节点,进行相关的测试。

另外需要注意的一点是,我们在这里求得的相交结果,都是保守的结果。如果错误地将不可见判定为可见,损失的只是一点点开销而已。但是如果将本来应该可见的物体,判定为不可见,就会照成错误的渲染结果。

2、快速得到视锥的六个平面方程[2]

通常我们拿到的摄影机视锥,都是投影矩阵的形式。这里我们就介绍下,通过投影矩阵,来快速计算出视锥六个平面的方法。

上面的公式中,黑点表示点乘,  表示矩阵的第  行。

经过变换后,  表示裁剪空间下的齐次坐标,根据齐次坐标的性质,我们可以推算出,要使点在视锥盒子内,需要满足条件:

同时可以算出点在视锥盒子外时,各种情况下的条件为:

设视锥平面的方程形式为  ,结合上面的条件,可以计算出最终每个平面的方程参数为:

如果我们的视锥是世界空间的,那么计算的过程也是一样的,把投影矩阵  做相应调整即可。

3、视锥和任意几何体相交计算

对于任意的几何体,都可以计算和视锥的相交信息,思路是将 几何体-视锥 之间的测试转化成 点-几何体 之间的测试,方法如下:

已知一个几何体(下图左上绿色)和视锥(下图左上蓝色),在几何体内选定任意一点p,将几何体平移,直到几何体和视锥刚好接触,保持几何体和视锥刚好接触的状态,将几何体在视锥表面滑动,p点移动后可以形成一个新的大几何体(下图右上橙色)。然后将几何体平移,同样是保持几何体和视锥接触,不过此时要将几何体放在视锥内部,使用类似的方式,得到一个新的小几何体(下图左下紫色)。得到新的大小几何体后,就可以和原始的点p位置做比较。如果点p位于小几何体内部,说明视锥时包含原始的几何体的,如果点p在大几何体内,小几何体外,说明二者是相交的关系。

4、视锥和球体相交计算

根据前面我们提到的方法,我们可以以简单地来计算球体和视锥相交信息。

取球体的球心点(下图左),将球心点在放在视锥上进行滑动,可以得到一个小的内部几何体和大的外部几何体(下图中)。和上面的判断方式类似,如果原始球心位于内部小几何体内,说明是包含关系。如果原始球心位于外部大几何体内,则是相交关系。为了使计算更加简洁,我们将可以将难以进行相关计算的圆角部分,直接简化成直角(下图右)。

另外一种计算进行相交测试的方式,是直接根据球心到六个平面的有向距离判断。将六个平面朝向视锥之外的面作为正向的半面,设球体半径为 r,如果球心到六个面的距离都小于 -r,说明是包含关系;如果球心到六个面的距离,都大于 r,则是不相交;除此之外,都是相交关系。严格来说,这种判断方式会在上图右边的小圆角外面区域造成错误判断,导致本来应该是不相交的结果,被错误地认定为是相交,不过因为我们使用的是保守式的相交测试,随意这种错误几乎没有影响。

视锥和长方体的相交测试

一种简单的方式,就是将长方体的八个角,经过投影变换,到裁剪空间中,然后在裁剪空间中进行相交测试。如果所有点都在[-1, 1]的裁剪空间内,就认为是包含关系,如果所有点都在裁剪空间外,就是不想交的关系。这种方式其实是手动模拟GPU的裁剪计算过程,优点是不需要从视锥中提前算出六个平面的方程。

我们也可以使用类似上面的相交测试方式,平移长方体并构建最小最大几何体,如下图所示。

另外一种方式,类似于上面计算平面和球体间距离的方式,只是改成使用平面和长方体间的距离计算方式,来计算视锥六个平面和长方体间的距离,通过距离来判断相交信息。

硬件剔除

这里来简单介绍下,可以使用 GPU 来自动完成的一些剔除过程,这些部分基本上不需要去手动实现,大部分只需要修改下图形API 中的相关设置即可。

Backface Culling

比如现在我们要观察一个不透明的球体,这个球体的背面,完全不会对渲染造成任何贡献,因此我们可以简单地将背面剔除,减少不需要的渲染开销。

判断三角形的正反面也比较简单,一种方式是计算出屏幕空间中三角形的有符号面积,另外一种方式是使用三角形的法线方向。

左:使用面积正负判断;右:使用法线方向判断

使用类似 DirectX的图形API,可以非常简单地使用硬件实现 Backface Culling。而且,在Pixel Shader中,可以使用SV IsFrontFace来简单地判断三角形的朝向方向。

需要注意的是,开启 Backface Culling,并不意味着整个渲染开销会降低一半左右。因为 Buffer 输入这一步,和 Vertex Shader 仍然是都会执行的,剔除掉的仅仅是光栅化和 Pixel Shader的运行开销。

在系列文章后面,我们会继续讲到使用 GPU Driven 来实现高级的 Backface Culliing。

Z-max Culling 、Z-min Culling、Early-Z

在Pixel Shader 开始执行前,如果我们开启了深度测试,GPU硬件会提前进行一次深度比较,这样如果深度测试失败,就可以跳过 Pixel Shader的执行,减少运行的开销。

提前进行的深度测试,包括 Z-max Culling 、Z-min Culling、Early-Z。

在 Pixel Shader 执行之前,我们拿到了当前当前像素点的深度值,还会提前进行一次深度测试,叫做 early-z/early depth。如果深度测试失败,则丢弃这个像素点,不会执行 Pixel shader。

Z-max Culling 、Z-min Culling、Early-Z都是由 GPU 硬件来自动完成的。当然,这些机制生效的前提是没有在 Pixel Shader中写入了自定义深度值、使用了 discard、或者向 Unordered Access View中写入了值,这些提前的丢弃机制就无法再生效了。这时,深度测试就会在 pixel shader 执行之后再执行,叫做 late depth test。

Z-Prepass

从上面我们提到的深度测试机制可以知道,对于完全不透明的物体,我们总是可以按照从近到远的顺序来渲染,来借助这些深度测试机制,丢弃不需要的渲染,获得性能提升。同时应尽量避免在 Pixel Shader 中修改深度,防止这些提前进行的深度测试机制失效。

一种常用的加速技术叫做 z-prepass,是一种软件程序的技术,会先将场景中的物体深度输出一遍,禁用 Pixel Shader,然后执行正常的渲染,此时将深度测试模式设置为 Equal。这样,由于 z-buffer是完全就绪状态,就会节省很多不需要的 Pixel Shader的执行开销。另外一个优点就是,很多时候我们需要 z-prepass 的过程提前得到 z-buffer,可以比较方便地计算出 SSAO 等信息。

需要注意的是,对于移动平台的GPU,往往有 TBDR/HSR 的机制,渲染提交不会立即执行,GPU再内部会自动进行z-prepass 的计算。除非我们需要进行SSAO等计算,否则一般不会在移动平台上使用 z-prepass。

z-prepass 和 early-z 是经常会搞混的两个东西,要特别注意区分。

/

论文算法视锥体-- Frustum Culling

一、背景知识
gluLookAt(px,py,pz, lx,ly,lz, ux,uy,uz)
  该函数定义一个视图矩阵,并与当前矩阵相乘: 
  第一组px, py,pz 相机在世界坐标的位置
  第二组lx,ly,lz 相机镜头对准的物体在世界坐标的位置
  第三组ux,uy,uz 相机向上的方向在世界坐标中的方向

gluPerspective (GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar)
  fovy是上下睁开的幅度,俯仰角度值;
  zNear表示近裁剪面到眼睛的距离,zFar表示远裁剪面到眼睛的距离。
  aspect表示水平方向的夹角;

二、视锥体模型


视锥体的核心
    第一步:    6个平面-- 远、近平面, 上下平面, 左右平面;(由近、远平面组成的"梯体")
    第二步:    9个顶点-- 近平面4个,远平面4个,最后加上相机位姿这个特殊点;
    第三步:    由相机位姿可以推算出相机的水平、垂直方向上的FOV以及与近平面和远平面的距离(也就是背景知识中涉及到的那些参数的换算);
    第四步:    由第三步还要计算近平面和远平面的Height 和 Width:
            
        Wnear = 2 * tan(.getHorizontalFOV() / 2) * neardist_;
        Hnear = 2 * tan(.getVerticalFOV() / 2) * neardist_;
            
        Wfar = 2 * tan(.getHorizontalFOV() / 2) * fardist_;
        Hfar = 2 * tan(.getVerticalFOV() / 2) * fardist_;

判断每一个3D点是否在第2步中每个平面的右边,也就是内侧,如果都在则说明是在相机视野内,反之则在视野之外.
    int FrustumG::pointInFrustum(Vec3 &p) 
    {
        int result = INSIDE;
        for(int i=0; i < 6; i++) {
            if (pl[i].distance(p) < 0)
                return OUTSIDE;
        }
        return(result);
    }

三、代码实现
随机生成一组3D空间点(500个),初始化相机位姿,得到第一次相机视野内数据如下(剩下181个):

其中,两个平面组成的范围为相机视野范围,其中绿色的点为当前视野范围内的数据点(经过剔除之后剩下的点);

移动相机位置,更新Frustum视野中的数据(剩下41个).


其中,红色的点为前一时刻在相机视野范围内经过剔除之后剩下的点(181)个,绿色的点为相机经过平移/旋转变换之后在当前视野下数据点(41)个。

参考文献
[1]. OpenGL–gluLookAt函数

[2]. openGL–gluPerspective函数

//

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Unity实时遮挡剔除是一种用于性能优化的技术,通过在渲染场景时动态地检测和移除被其他物体遮挡的不可见物体,提高渲染效率和帧率。 实时遮挡剔除的原理是通过摄像机的视锥体来确定被剔除的物体,只有在视锥体内的物体才会被渲染,而视锥体外的物体则会被剔除。这样可以避免不可见物体的渲染,减少对GPU、CPU和带宽的压力,提高游戏的性能和流畅度。 Unity实时遮挡剔除的步骤主要包括: 1. 确定摄像机的视锥体,即摄像机能够看到的范围。 2. 对于每个物体,判断其是否在视锥体内。如果在视锥体外,就剔除它。 3. 如果物体在视锥体内,继续检测是否被其他物体遮挡。如果被遮挡,也将其剔除。 4. 对剩下的可见物体进行渲染。 Unity实时遮挡剔除有助于提高游戏的渲染性能,尤其是在大型场景或者复杂的游戏世界中。它可以减少渲染物体的数量,加快渲染速度,使游戏更加流畅。此外,通过合理的遮挡剔除设置,还可以减少GPU和CPU的负担,让游戏在更低的硬件要求下运行。 总之,Unity实时遮挡剔除是一种重要的性能优化技术,能够提高游戏的渲染效率和帧率,为玩家提供更好的游戏体验。 ### 回答2: Unity实时遮挡剔除(Real-time Occlusion Culling)是一种用于提高游戏性能的技术,旨在减少对不可见物体的绘制。在游戏场景中,有些物体可能被其他物体遮挡,这些被遮挡的物体在渲染时不需要显示,因此可以将其剔除,从而节约计算资源。 Unity实时遮挡剔除的实现原理是通过预先计算场景中不同物体的可见性。首先,进行场景的静态分析,生成一张场景中所有物体的可见性图(Occlusion Map),记录每个点是否可见。接下来,通过相机的视锥体(视野范围),对于视锥体内的物体,通过检查其在可见性图中的位置来判断其可见性。如果物体被视锥体外的其他物体遮挡,那么它将被剔除,否则将进行渲染。 通过使用Unity实时遮挡剔除,我们可以提高游戏的渲染效率,减少不必要的绘制操作,从而改善游戏的性能和流畅度。这对于那些需要处理大量复杂场景的游戏特别有用,因为它可以在运行时动态地确定哪些物体需要渲染,减轻了GPU和CPU的负担,使游戏更加流畅。 Unity实时遮挡剔除虽然对场景的可见性进行了优化,但也有一些限制。例如,在动态物体或需要频繁更新的场景中,无法准确地预计可见性,因此需要使用其他技术进行补充,如级别细化(LOD)和动态批处理等。 综上所述,Unity实时遮挡剔除是一种采用预先计算可见性的技术,旨在提高游戏性能。通过剔除不可见的对象,减少了对它们的渲染,使游戏在复杂场景下运行更加流畅。 ### 回答3: Unity的实时遮挡剔除是一种技术,可以在场景中动态隐藏不可见的物体,从而提高渲染的效率。这个技术可以有效地避免不必要的渲染,减少GPU的负担,从而提高游戏性能。 在Unity中,实时遮挡剔除是通过一个叫做视锥裁剪器(Frustum Culling)的技术来实现的。视锥裁剪器实际上是一个虚拟的摄像机,它只渲染在视锥体内的物体。通过将在视锥体外的物体从渲染队列中剔除掉,可以减少不必要的渲染操作,提高渲染效率。 Unity的实时遮挡剔除还使用了一种叫做遮挡剔除(Occlusion Culling)的技术。遮挡剔除是通过判断一个物体是否被其他物体遮挡住来进行的。当一个物体被其他物体遮挡住时,该物体的渲染操作就会被剔除掉,从而减少不必要的渲染。 Unity的实时遮挡剔除在编辑器中可以通过配置设置来应用。通过在场景中添加遮挡剔除区域,可以指定哪些物体应该被剔除。而且,Unity还提供了一些调试工具,可以帮助开发者进行优化,如场景的可视化遮挡剔除图和性能分析器。 总之,Unity的实时遮挡剔除是一种有效的渲染优化技术,可以提高游戏性能,减少不必要的渲染。通过视锥裁剪器和遮挡剔除的配合使用,可以在保证画面质量的同时提高游戏的帧率和流畅度。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值