简易视锥剔除技巧总结

简易视锥剔除技巧总结

1.      背景

视锥剔除可以大大提高3D场景的渲染效率。但随着显卡的发展,CPU上过多的视锥剔除计算可能会消耗过多的时间,从而拖累了整体的渲染速度。同时,在我最近接触到的一些项目中,经常需要做一些比较特殊的场景,通用的视锥平面相乘容易出现误差导致误判,而且在调试的时候比较麻烦。

因此,我在实际编程中喜欢用一些比较简单快速的视锥剔除函数。

 

2.      平面场景

a.       城市场景

利用二维视锥投影代替三维包围盒。

城市场景由于主要是建筑物。这样的场景一般建筑物的高度比较一致,如果采用地表与视锥求交作为剔除的依据,则当镜头仰视时容易把建筑物误剔除,而如果将地表拉高做成立方体与视锥求交作为剔除依据,则比较难确定拉高的高度。

我采用的办法是将视锥投影到地面上,这样就不需要再确定拉高的高度了。在具体剔除的时候,同样可以利用包围球、包围盒之类的方法进行计算,只需要把三维的判断公式改为二维。

 

b.      四叉树组织式的无限规模场景

利用视锥投影包围盒确定根节点。

现在有很多场景的规模是无限或不确定的,这时四叉树如果从整个组织树的根节点开始判断,则有可能造成浪费,甚至有时候无法得知根结点。

我的做法是将视锥投影后的包围盒向上取对数求得一个可以包围视锥的最小四叉树节点,将此节点作为根结点在进行四叉树递归和剔除。

 

3.      其他场景

有时我们需要构造一些其他形状的场景。例如地球等球体。视锥剔除时我首先将视锥假设成为一个90度角的圆锥体(当然也可以改为其他度数),然后按以下的步骤进行剔除。

a.       距离剔除

根据视锥的远近平面可以得到它的可见距离范围。如果被测物体在 此距离外,可直接剔除。当被测物体相对于视锥比较大时,我采用类似于包围球的方法进行简易判断,即物体中心到摄像机的距离减去物体包围球半径所得的值大于视点到视锥远平面的距离,则判断为不可见。

经过此步骤,可以得到以视点为中心的球状场景。我可以用这类方法作为显存加载的依据,因为一般用户在漫游时比较喜欢原地旋转镜头,不大乐意接受旋转时带来的卡帧或者场景空白的效果。

 

b.      背面剔除

物体向量点乘视向量,得出的结果时两个向量长度积乘以cos夹角值之积,当这个值小于0时,表明这个物体在视锥的背面,可以剔除。

如果被测物体相对于视锥比较大,我采用的时取边界点进行判断。如果全部小于0则完全不可见,部分小于0则部分可见。

经过此步骤,理论上可以剔除a步骤后的一半场景对象。

 

c.       视锥夹角剔除

b步骤中物体向量点乘视向量的乘积经过单位化,可以得到两个向量夹角的cos值。当此cos值大于视锥夹角的cos值时,一般为不可见,我的视锥为90度,半角为45度,所以阀值取了0.707

但测物体相对于视锥比较大时,如果只以边界点判断,则有可能将离镜头很近或很大的物体误判为不可见。因为边界点可能全部在视锥夹角范围外,但是物体是可见的。我解决此问题的方法是将各边界点点乘右向量,如果结果有正有负,则说明该物体跨越视锥上向量和视向量组成的平面,因此还是可见的;如果全部为正或全部为负,则说明他们全部在此平面的一侧,为不可见的。

这个判断回将视锥背面同样范围的物体判为可见,因此背面的物体需要现在步骤b中剔除。

经过此步骤,理论上可以剔除b步骤后的一半场景对象。

 

d.      增加插值点判断

如果物体比较不规则,取边界点时不容易取到全部的边界点,因此还是容易造成误判。此时可以再增加一些插值点,按c步骤判断是否在视锥夹角内,如果在的话仍为部分可见。

 

e.       其他判断

考虑到最后的屏幕投影,视锥有可能出现长宽比相差较大,如果需要的话可以在判断时采用更精确的计算。例如采用2个不同方向的仰角分别判断是否在视锥角内。但此加入步骤后视锥判断的时间消耗已经与用4个视锥平面与物体相乘求交的消耗差不多了。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 相机视锥(Camera Frustum)是在计算机图形学中用于表示相机在三维空间中可见范围的几何形状。通过计算相机视锥代码,我们可以获得相机的射线方向和视野范围,从而帮助我们进行可视化渲染等操作。 以下是一个简单的计算相机视锥的代码示例: 1. 首先,我们需要获取相机的投影矩阵(projection matrix)和相机的视图矩阵(view matrix),这两个矩阵通常由引擎或库提供。 2. 然后,我们可以使用这两个矩阵来计算相机视锥的六个面(near, far, left, right, top, bottom)。 3. 首先,我们需要将投影矩阵和视图矩阵相乘,得到投影视图矩阵(projection-view matrix)。 4. 接下来,我们使用逆转置矩阵的转置以及四个坐标分量计算各个面的法线和距离。根据相机视锥的特性,这些面的法线向量和距离可以帮助我们计算视锥的六个面的方程式。 5. 最后,我们可以将这些值存储在一个数据结构中,以供后续的计算和使用。 这只是计算相机视锥的一个简单示例,实际上,相机视锥的计算可能涉及更多复杂的操作和算法,我们需要考虑到相机的位置、方向、视角等因素。 通过计算相机视锥,我们可以实现一些基于相机的功能和效果,比如裁剪不可见物体、实现可见性检测、绘制远近景物体等。这对于实现高性能的可视化渲染是非常重要的。 ### 回答2: 相机视锥是指在计算机图形学中,用来确定在屏幕上显示的可见场景的范围。在3D图形渲染中,相机视锥由近裁剪面、远裁剪面、左裁剪面、右裁剪面、上裁剪面和下裁剪面六个平面组成,形成一个截锥体。计算相机视锥的代码通常需要用到视图矩阵、投影矩阵和顶点坐标等信息。 一个简单的计算相机视锥的代码示例如下: 1. 定义视图矩阵和投影矩阵。 ``` matrix4 viewMatrix = ...; matrix4 projectionMatrix = ...; ``` 2. 定义顶点坐标。 ``` vec3 vertex1 = ...; vec3 vertex2 = ...; ... ``` 3. 将顶点坐标变换到裁剪空间。 ``` vec4 clipVertex1 = projectionMatrix * viewMatrix * vec4(vertex1, 1.0); vec4 clipVertex2 = projectionMatrix * viewMatrix * vec4(vertex2, 1.0); ... ``` 4. 计算裁剪空间中的四个顶点(左下、左上、右下、右上)。 ``` vec4 bottomLeft = clipVertex1; vec4 topLeft = clipVertex2; vec4 bottomRight = clipVertex2; vec4 topRight = clipVertex1; ``` 5. 将裁剪空间中的顶点坐标变换到规范化设备坐标空间(NDC)。 ``` vec3 ndcVertex1 = bottomLeft.xyz / bottomLeft.w; vec3 ndcVertex2 = topLeft.xyz / topLeft.w; ... ``` 6. 计算相机视锥的近裁剪面、远裁剪面以及左、右、上、下裁剪面在规范化设备坐标空间中的位置。 ``` float nearPlane = ndcVertex1.z; float farPlane = -ndcVertex2.z; float leftPlane = ndcVertex1.x; float rightPlane = ndcVertex2.x; float bottomPlane = ndcVertex1.y; float topPlane = ndcVertex2.y; ``` 以上是一个简单的计算相机视锥的代码示例。一般来说,还可以根据需要添加更多功能,例如视锥的可视体积、剔除不可见的物体等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值