1.场景剔除描述
可见性问题作为计算机图形学的一个基本问题,它的主要目的是对给定的场景和观察视点,通过对遮挡关系进行快速判断,扔弃大量不需要绘制的图形对象,降低场景的复杂度,增加场景的流畅度,最终实现低负荷绘制。
以大型车辆或飞机模型作为典型的稠密型场景,在任何一个视点均只能看到模型的冰山一角。其它如飞机内部场景,被机身遮挡了大部分场景。常用的一些方法有视域剔除,背面剔除,遮挡剔除,对大规模场景,用得最多的方法是遮挡剔除。
遮挡剔除技术伴随计算机图形学的发展而发展,在早期的 3D 游戏中,传统的遮挡剔除就开始被应用在图形渲染中,优化图形产品的渲染性能。
2.OpenGL遮挡查询方法介绍
接下来将要介绍利用硬件遮挡查询(Occlusion Query)的剔除方案。下图为利用OpenGL实现遮挡查询的方法。
//生成一个查询对象
GLuint query;
glGenQueries(1, &query);
//开始查询
glBeginQuery(GL_SAMPLES_PASSED, query);
//渲染你想要检查的对象
glDrawArrays(GL_TRIANGLES, 0, 36);
//结束查询
glEndQuery(GL_SAMPLES_PASSED);
//获取查询结果
GLuint samples;
glGetQueryObjectuiv(query, GL_QUERY_RESULT, &samples);
如果samples
的值大于0,则表示被检查的对象至少被渲染了一次,即它至少部分处于屏幕上的可见区域内。如果samples
的值为0,则表示对象完全不可见,没有被渲染到屏幕上。
但需要注意的是,查询的结果是基于上一次绘制的图像进行计算的,这就使得在相机视角变化较大时,查询的结果不准确。
3.遮挡剔除方案关键技术
1.八叉树生成与检索
在处理大规模网格数据时,首先需要将网格数据放入vtk的八叉树中。八叉树是一种空间划分树结构,可以将三维空间划分为八个子空间,以此类推,直到每个子空间只包含一个或少量对象。将网格数据放入八叉树中,可以有效地组织和管理大规模的网格数据,提高查询效率。
2.视锥剃齿
视锥剔除是一种基于相机视锥的剔除技术,可以排除相机视野之外的不可见对象,减少渲染开销。通过检测网格对象是否在相机视锥内部,可以快速确定哪些对象需要被渲染,哪些对象可以被剔除。具体到实现步骤如下:
-
确定相机视锥:获取相机的位置和视锥参数,计算相机视锥的六个裁剪平面。
-
遍历八叉树:从根节点开始,递归或迭代地遍历八叉树的节点。
-
进行遮挡查询:对于每个遍历到的节点,判断节点的包围盒与相机视锥的相交情况。如果节点完全在相机视锥之外,则可以确定该节点及其子节点都被遮挡了,可以跳过对其子节点的遍历。如果节点与相机视锥相交,则需要进一步检查节点内部的对象是否被遮挡。
3.基于八叉树的遮挡查询
然后利用八叉树和OpenGL进行查询遮挡剔除。在渲染过程中,利用八叉树对场景进行空间分割,快速确定可能造成遮挡的对象。然后利用OpenGL提供的遮挡剔除技术,可以检测哪些对象被遮挡,从而减少不必要的渲染操作,提高渲染效率。
在进行视锥剔除后,实现遮挡查询的具体步骤如下:
-
硬件遮挡查询:获取当前节点的立方体包围合的遮挡查询结果。
-
判断继续查询:根据查询结果,决定是否继续遍历当前节点的子节点。
-
对于被遮挡的节点或对象,可以跳过渲染操作,从而实现遮挡剔除。