我在 GLSL 中进行“光线行进距离场”(正确的行话:球体追踪)。为了在其之上实现圆锥行进(并且无论是否添加圆锥行进,也尽量减少光线行进步骤数),我需要估计任意给定距离处的射线圆锥的半径。
回想一下光线行进距离场,当到对象的距离小于阈值时,就会记录“命中”,通常以名为 closeLimit 或 epsilon 的代码表示。如果我们随着行进距离以指数方式增加该阈值,则可以将该阈值视为相当于射线锥半径 - 这样,我们不会将细射线直线射入空间,而是根据透视投影扩展锥体。这更准确地涵盖了捕捉“正确的”远处物体(此时,让我们暂时忽略混合 Material 和过滤距离 t 处视锥中所有相交物体的法线的问题......)。
在第 0 步,该半径可以近似为诸如
float fInitialRadius = 1 / min(screenwidth, screenheight);
通过将起始半径应用于距离,可以在每一步以指数方式增加:
fNearLimit = fTotalDist * fInitialRadius; // after each raymarching step
这工作正常,但仍然有工件。如果我使用 fInitialRadius*fInitialRadius(由于 640px 帧缓冲区的初始半径和单位宽度 View 平面为 1/640,导致数字更小),我会得到更少的伪影和更准确的结果。但这两种方法都不准确,第一种方法太急切(过早增加半径太多),后者太懒(增加半径太少太晚)。
增加 fNearLimit/给定距离处的圆锥半径的最准确因素很可能会考虑到我当前的视野,并且会根据视野是 45°、60°、90° 或...
TL;DR:我想知道给定距离处圆锥体半径的正确计算或最可接受的近似值是什么给定步骤 0 处的初始像素半径和视场角?
最佳答案
圆锥体的半径与其尖端的距离线性对应。 (否则它就不是圆锥体!)
因此,如果您的圆锥体在与屏幕平面相交时具有 initialRadius
,那么稍后:
radius(distance) = distance * initialRadius / focalDistance
您必须在每一步重新计算该值,因为每一步都会花费不同的距离。
这里distance
是光线到相机的距离,focalDistance
是屏幕平面到相机的距离。
(对于不在屏幕中心的像素,使用屏幕平面上的像素距相机的距离而不是 focalDistance
可能更准确。)
(或者也许更好,根本不使用距离。只需使用深度代替,即仅垂直于屏幕平面的矢量分量。这可能如果您已将场景旋转到相机框架中,则为您的 z 轴或 y 轴。)
关于3d - 如何计算光线行进中一定距离处的视锥半径(即像素的大小)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10492590/