2

我是 GLSL 中的“光线追踪距离场”(正确的术语:球体追踪)。为了在它上面实现锥形行进(并且还要最小化光线行进步骤的数量,无论是否添加了锥形行进),我需要估计任何给定距离处的光线锥的半径。

回想一下 raymarching 距离场,当与对象的距离小于阈值时,会记录一次“命中”,通常使用名为 nearLimit 或 epsilon 的代码。如果我们将这个阈值随着行进的距离呈指数增加,这个阈值可以看作等同于射线锥半径——这样,我们不会将细直线射入太空,而是根据透视投影扩展锥体。这更准确地涵盖了捕捉“正确”的远处物体(此时让我们暂时忽略在距离 t 处的视锥中混合材质和过滤所有相交物体的法线的问题......)。

在第 0 步,这个半径可以近似为诸如

float fInitialRadius = 1 / min(screenwidth, screenheight);

然后可以通过将起始半径应用于距离,在每一步以指数方式增加:

fNearLimit = fTotalDist * fInitialRadius;  // after each raymarching step

这工作正常,但仍然有工件。如果我使用 fInitialRadius*fInitialRadius(由于 640px 帧缓冲区和单位宽度视图平面的初始半径为 1/640 导致数字更小),我会得到更少的伪像和更准确的结果。但是这两种方法都不准确,第一种过于急切(过早地增加半径),后者过于懒惰(过早地增加半径)。

在给定距离处增加 fNearLimit / 圆锥半径的最准确因素必须很可能考虑到我当前的视野,并且会根据视野是 45° 或 60° 或 90° 还是...

TL; DR:我想知道给定距离的圆锥半径的正确计算或最可接受的近似值是什么?给定步骤 0 的初始像素半径和视场角?

4

1 回答 1

3

圆锥的半径线性对应于距其尖端的距离。(否则它不是一个圆锥体!)

因此,如果您的锥体initialRadius在与屏幕平面相交时具有,那么稍后:

radius(distance) = distance * initialRadius / focalDistance

您必须在每一步重新计算该值,因为每一步都会带您走不同的距离。

这里distance是光线到相机focalDistance的距离,是屏幕平面到相机的距离。

(对于不在屏幕中心的focalDistance像素,使用屏幕平面上像素与相机的距离可能更准确。)

(或者也许更好,根本不使用距离。只需使用深度,即仅垂直于屏幕平面的矢量分量。如果您已将场景旋转到,这可能是您的 z 轴或 y 轴相机框架。)

于 2012-07-05T17:36:39.423 回答