我在我正在开发的光线追踪器中遇到了一个有趣的问题。场景中的对象存储在边界卷层次结构中。每个单独的对象都封装在层次结构的叶节点的边界框中,并具有与之关联的矩阵变换。
现在,我被教导在光线追踪中对物体进行矩阵变换的方法是通过物体矩阵的逆变换每条射线,然后查看是否存在交点。在伪代码(没有bvh树)中它看起来像这样:
float minimum_distance = FLOAT_MAX;
Intersection closestHit = null;
for(each object in scene)
{
Matrix transform = object.transform();
Matrix inverse = transform.inverse();
Ray transRay = transformRay(eyeRay, inverse);
Intersection hit = CollisionTest(transRay, object);
if(intersectionFound)
{
if(hit.distance() < minimum_distance)
{
closestHit = hit;
}
}
}
Shade(closestHit);
由于场景对象没有边界结构,您可以遍历每个场景对象并通过每个对象的矩阵变换光线进行测试。但现在想象以下具有BVH树的场景:
ROOT
Left Box Right Box
| |
V V
object A object B
现在假设我们有一个eyeRay,只有正确的交叉点。光线只会检查右边框中的交叉点对象,并完全忽略左框中的任何对象(这是将对象置于这样的层次结构中的主要优点......以避免不必要的检查)。 p>
然而,左框中的对象A具有与之关联的缩放变换,当应用时,它将拉伸对象A,使其跨越到右边框区域。如果允许光线对照场景中的每个对象进行自我检查,您会发现当对象A的变换的逆矩阵应用于光线时,将找到一个交点。但是,永远不会允许光线进行转换检查,因为未转换的对象A正好位于左侧框中。因此,将错过交叉点,结果将是部分渲染的对象A.
所以我的问题是如何解决这个问题?我不想放弃使用边界体积层次结构,但我不知道它与上述反射光线算法的兼容性。有什么想法吗?
答案 0 :(得分:1)
首先请注意,有许多BVH树专业化。更常见的是排除边界体积与邻居节点的交叉(即左框不能与右框相交)。
现在,绑定卷的整个点是它绑定了底层对象。因此,如果该对象具有将其缩放超过边界体积的变换,那么这意味着边界体积不是正确的边界体积(BV)。
两种解决方法,如果在未经过变形的几何体上计算边界体积,则在检查光线边界体积交点时,首先将BV变换为与对象相同的坐标系。
根据您正在做的事情,更有效的方法可能是直接在变换对象(缩放,平移等)对象上计算BV。这样,在进行初始ray-BV检查时,您无需转换框(或光线)。
希望有所帮助。