具有边界体积层次的光线跟踪对象矩阵变换



我在开发的光线跟踪器中遇到了一个有趣的问题。场景中的对象存储在边界体积层次中。每个单独的对象都被封装在层次结构的叶节点的边界框中,并具有与其相关的矩阵变换

现在,我被教导在光线跟踪中对对象进行矩阵变换的方法是通过对象矩阵的逆变换每条光线,然后看看是否存在交集。在伪代码(并且没有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,它只与右边的方框相交。光线将只检查右侧框中的相交对象,而完全忽略左侧框中的任何对象(这是将对象放在这样的层次中的主要优点…以避免不必要的检查)。

但是,左框中的对象A有一个与其关联的缩放变换,当应用该变换时,将拉伸对象A,使其跨越到右框区域。如果允许光线对照场景中的每个对象进行自身检查,您会发现,当将对象A的逆变换应用于光线时,会发现一个交点。但是,永远不允许光线进行变换检查,因为未变换的对象A正好位于左侧框中。因此,交叉口将被错过,结果将是部分渲染的对象a。

所以我的问题是我该如何解决这个问题?我不想放弃使用边界体积层次,但我看不出它如何与上述反转光线的算法兼容。有什么想法吗?

首先要注意的是,BVH树有许多专门化。更常见的方法排除了边界体积与相邻节点的相交(即"左框"不能与"右框"相交)。

现在,边界体积的整个点是它对基础对象的边界。因此,如果该对象有一个变换,使其缩放超过边界体积,那么这意味着边界体积不是一个合适的边界体积(BV)。

有两种方法可以解决这个问题,如果边界体积是在未转换的几何体上计算的,那么在检查光线边界体积相交时,首先将BV转换到与对象相同的坐标系。

根据您所做的操作,一种更有效的方法可能是直接在变换的对象(缩放、平移等)上计算BV。这样,在进行初始光线BV检查时,就不需要变换长方体(或光线)。

希望能有所帮助。

相关内容

  • 没有找到相关文章