我正在渲染一种旧的游戏格式,其中包含构成您所在的网格的列表。我终于使PVS(从另一个区域可见的区域)正常工作,并且切出了很多我不知道的网格需要渲染,但不需要太多。所以现在,我应该渲染的网格列表仅包括我可以看到的其他网格。但这并不完美。仍然有大量的网格,其中包括距离剪辑很远的网格。

现在,首先,我要剔除我认为不是平截头体的网格。我听说边界框是执行此操作的最佳方法。有谁知道我该怎么做吗?我知道我需要最大点(x,y z)和最小点(x,y z),以便一个盒子包含所有顶点。

然后,我是否检查并认为这些点中的任何一个都处于视锥状态?这么简单吗?

谢谢!

最佳答案

AABB或“轴对齐边界框”是用于测试两个3D区域相交/包含的非常简单快速的对象。

如您所建议的,您正在为要比较的两个区域(例如,描述视锥的区域和描述网格的区域)计算最小和最大x,y,z。它是轴对齐的,因为后续的立方体的边与坐标系的每个轴平行。显然,这可能会有点不准确(相交/包含的假阳性,但绝不会假阴性),因此,一旦使用AABB测试过滤列表,就可以考虑对其余的网格进行更准确的测试。

您按以下方式测试交叉点/围堵:

F =视锥的AABB

M =网格的AABB

bool is_mesh_in_frustum(const AABB& F, const AABB& M)
{
    if( F.min.x > M.max.x || M.min.x > F.max.x || F.min.y > M.max.y || M.min.y > F.max.y || F.min.z > M.max.z || M.min.z > F.max.z )
    {
        return false;
    }
    return true;
}

您还可以查找用于边界球,定向边界框(OBB)和其他类型的边界体积的算法。根据要渲染的网格数量,您可能需要或可能不需要更准确的方法。

首先要创建AABB,您可以简单地遍历网格的顶点并记录遇到的最小/最大x,y和z值。

还要考虑一下,如果网格不变形,那么网格坐标空间中的边界框将是静态的,因此一旦获得顶点数据,您就可以为所有网格计算AABB。

然后,您只需要确保在对每个渲染通道进行测试之前,将预先计算的AABB最小和最大顶点转换为视锥坐标空间。

编辑(发表评论):

AABB可以提供误报,因为它充其量是您所包围区域的确切形状,但通常比您所包围的区域大。

考虑一个球体,如果您使用AABB,就像将篮子球放入盒子中一样,那么所有这些间隙都在球无法到达的盒子角上。

或在平截头圆锥体朝向摄像头向内倾斜的情况下,它的AABB会简单地沿轴朝向摄像头连续笔直,从而有效地限制了比摄像头可见的区域。

这是不准确的根源,但绝不应该导致您剔除甚至位于视锥内部的物体,因此,最糟糕的是,您仍将绘制一些靠近相机但仍位于视锥外部的网格。

您可以通过以下方法纠正此问题:首先进行AABB测试,然后生成较小的返回true的网格列表,然后在该较小的列表上执行更准确的测试,并为视锥和/或网格设置更准确的边界体积。

10-08 11:26