OpenGL边界框深度计算

5
我正在编写一个OpenGL应用程序,使用深度排序的透明/半透明算法。
我的第一种方法是计算所有对象的包围盒中心到相机的距离,但我发现一个包围盒可能比其他包围盒更靠近相机,但其中心点却更远。
这些包围盒的方向可以不同,因此它们的轴并未对齐。
如何正确地计算包围盒到相机的距离?

2
盒子是否与轴对齐? - Nico Schertler
不一定,它的矩阵变换可以是不同的。 - Roberto Peribáñez Iglesias
2
你需要定义什么是从边界框到相机的距离,通常是从中心到眼睛位置的距离,否则,一个框将有多个到相机的距离。也许你想要的不是从中心开始的距离。而是最靠近相机的点?或者你需要先将它们投影到“最重要的平面”上,然后再进行计算。 - concept3d
这两个对象都是透明的吗? - concept3d
是的,这两个对象都是透明的。 - Roberto Peribáñez Iglesias
2个回答

1

对于每个定向边界框 (OBB),计算从 cameracentre 的距离涉及到性能开销较大的 sqrt,因为它是欧几里得距离函数的本质;此外,你需要最接近相机的盒子,通过测量到中心的距离来解决这个问题并不太合理。

替代方法

Z 排序

如果你知道盒子在相机空间中的顶点,将它们按 Z 值排序可以给你最接近相机的盒子。包含该点的盒子将是最接近相机的盒子。然而,由于 OBB 通常按其中心、方向和大小存储,因此人们通常不会立刻拥有盒子在相机空间中的顶点;因此,通常需要将所有盒子的所有顶点从盒子空间转换到相机空间;这可能会很耗费资源,但如果在 GPU 上执行,可能还好。

交集测试

这是我能想到的替代方案,可能比排序更快但不够精确,就是在这些盒子上进行快速的光线-obb相交测试(使用ray.origin = cameraray.direction = obb.centre - camera)。每个测试会返回一个t,表示该盒子上发生碰撞的向量上的距离;将ray乘以t并仅取其Z分量,基本上会给出该向量在Z轴上的投影(这将是光线击中盒子的点的Z坐标);最小Z分量的那个将是沿Z方向从相机最近的盒子。 此页面包含光线-obb测试的算法和实现;它使用了Kay-Kajiya在《Real-Time Rendering》中描述的平板方法

2
你可以通过使用distance**2而不是使用distance来排序,而且不需要使用sqrt() - gg349
+1 但是,相机到中心的距离并不能解决OP的问题;这正是问题的关键所在;因此我提出了另外两个解决方案。 - legends2k
你在使用哪种光线进行相交? - GuyRT
射线是从相机到OBB中心的射线;这就是我说这只是一个近似值的原因。要找到实际的射线,正确的做法是在某个空间中取OBB的边缘并在那里进行排序,即答案中的第一种方法。 - legends2k

1
最好的近似方法是使用在相机空间中最远的OBB点Z分量(在依据手性确定的情况下,具有最高/最低Z分量的点)对对象进行排序,因此称为Z排序。也可以使用平方距离。

记住,在发出绘制命令时,您需要首先渲染其中一个对象(除非您将每个对象都拆分为单独的对象,否则无法部分绘制它们)。

在您的情况中,应首先绘制object1,并注意它沿相机轴具有最远的点。

算法简述:

  • 将每个边界框点转换为相机空间。
  • 找到每个框架沿相机Z轴的最远点。这将成为每个边界框的深度键。
  • 使用找到的深度键对框进行排序。
  • 从后向前绘制对象。

P.S. 我还没有想到可能失败的情况,所以我说是近似值。


如果对象2向左延伸得更远,以至于它有最远的点,会怎样呢? - Wyzard
@Wyzard 注意:相机空间中最高/最低的Z分量。 - concept3d
我认为Wyzard说得有道理。我们知道物体1应该在物体2之前绘制(这样我们才能看到物体1穿过物体2),因为从相机的角度来看,这两个物体“重叠”。如果我们只看每个物体最远的点来确定哪个应该先绘制,就像你建议的那样,在问题的示例中它可以正常工作,因为物体1的背面离相机最远。但是想象一下,如果物体2被扩展了一点(或者物体1被缩短了一点),使得物体2的背面现在离相机最远,那么obj2将会在obj1之前绘制。 - DisplayName
仅从点的外观上看似乎不可能。在https://www.opengl.org/wiki/Transparency_Sorting#How_to_Sort中有一个很好的简短描述。必须以某种方式查看两个对象的“跨度”... - DisplayName
@Bjarke 嗯,这只是一个近似值,正如我在答案中提到的那样,这通常是一个难题,根据我的经验,游戏通常会尽量避免边缘情况。 - concept3d
@concept3d 你说得对。这是一个很好的近似值(我点了个赞),但我认为重要的是要提到有些情况下它会失败(考虑“P.S.”和Wyzards的评论)。OP的中心点方法可能同样好,而且我认为他的问题是如何处理边缘情况。但是,如果你不能接受“简单”方法带来的伪影,那么它可能变成一个相当复杂的问题。看起来许多游戏引擎只使用简单的方法,并避免将对象放置在会出现伪影的位置... - DisplayName

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接