opengl - 查看视锥体剔除问题

标签 opengl 3d computer-science computational-geometry direct3d

所以,我正在尝试实现视锥体剔除。这里的问题是,在我做到这一点之前,我需要了解一些事情。

首先是平面相交:

我的理解是平面可以通过3个点来定义;我们将它们称为 p0、p1 和 p2

鉴于此,我们知道平面的法线可以计算如下:

(伪代码)

vec3 edge0 = p1 - p0;
vec3 edge1 = p2 - p0;

vec3 normal = normalize( cross( edge0, edg1 ) ) // => edge1 X edge2 / length( edge1 X edge2 );

现在,假设我们有一个函数,它基本上告诉我们给定点是否以某种方式“穿过”平面。

(摩尔伪代码)

bool crossesPlane( vec3 plane[3], vec3 point )
{
    vec3 normal = getNormal( plane ); // perform same operations as described above
    float D = dot( -normal, plane[ 0 ] ); // plane[ 0 ] is arbitrary - could just as well be the 2nd or 3rd point in the array

    float dist = dot(normal, point) + D; 

    return dist >= 0; // dist < 0 means we're on the opposite side of the plane's normal. 
}
<小时/>

这背后的逻辑推理是,由于视锥体包含六个独立的平面(近、远、左、上、右、下),我们希望捕获这六个平面中的每一个,并本质上“通过”对于单个点(一个点,对该点进行六次测试),将它们传递给 CrossesPlane() 函数。

如果对 crossesPlane() 的这六个调用之一返回 false,那么我们想要剔除有问题的点,从而有效地导致该点被视锥体,当然该点不会被渲染。

问题

  • 这是正确剔除视锥体的正确方法吗?
  • 如果是这样,为给定的多边形获取任意顶点列表,并使用此方法对每个顶点执行此测试,是否是一种有效的方法?
  • 虽然 AABB 可以用来代替多边形/网格进行剔除测试,但它们在这种情况下仍然常用吗?它们仍然被视为“通用”goto 方法吗?

注意

如果 D3D 和 OpenGL 之间有任何值得一提的实现差异,我们将不胜感激。

最佳答案

  • 是的,这本质上是视锥体剔除点的正确方法。
  • 不,对每个顶点单独执行此测试并不是剔除任意多边形的有效方法。考虑与平截头体相交的单个非常大的三角形的情况:它的所有顶点可能都在平截头体之外,但该三角形仍然与平截头体相交并且应该渲染。
  • AABB 可用于视锥体剔除,并且通常是一个不错的选择,尽管您仍然需要处理 AABB 的所有顶点都在视锥体外部但与视锥体相交的情况。边界球使内部/外部测试稍微简单一些,但往往在它们所包含的对象周围有更宽松的边界。然而,这通常是一个合理的权衡。

关于opengl - 查看视锥体剔除问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19782711/

相关文章:

opengl - 有没有办法纯粹在着色器中应用正弦波失真效果?

c++ - 如何清除opengl着色器缓存

ios - 在 iOS 中显示纹理 3D 模型

python - 如何更正我的朴素贝叶斯方法返回极小的条件概率?

programming-languages - 如果所有可计算的事情都可以在 1 秒内完成,编程语言会是什么样子?

opengl - 将透明纹理渲染到 glTexture

c++ - 用 C++ 绘制标量和 vector 场的最简单方法?

matlab - 从 3D 数组中提取任意旋转的数据平面作为 2D 数组

Java:多线程和二维线程

algorithm - 线程 I/O 重新排序缓冲区的标准术语?