3d 如何计算光线行进中距离处的视锥半径(即像素大小)?

3d 如何计算光线行进中距离处的视锥半径(即像素大小)?,3d,glsl,antialiasing,raytracing,raycasting,3d,Glsl,Antialiasing,Raytracing,Raycasting,我是GLSL中的“光线行进距离场”(恰当的行话:球体跟踪)。要在其顶部实现“圆锥体行进”(并且无论是否添加“圆锥体行进”(cone marching)),都要最小化“光线行进”(ray marching)步骤的数量,我需要估计任意给定距离处光线圆锥体的半径 回想一下,在光线行进距离字段中,当到对象的距离小于阈值时,会记录“命中”,通常代码为nearLimit或epsilon。这个阈值可以被视为等同于射线锥半径,如果我们随着移动距离的增加而指数增加的话——这样,我们就不会向空间中发射直线细射线,而

我是GLSL中的“光线行进距离场”(恰当的行话:球体跟踪)。要在其顶部实现“圆锥体行进”(并且无论是否添加“圆锥体行进”(cone marching)),都要最小化“光线行进”(ray marching)步骤的数量,我需要估计任意给定距离处光线圆锥体的半径

回想一下,在光线行进距离字段中,当到对象的距离小于阈值时,会记录“命中”,通常代码为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步的初始像素半径和视场角度?

圆锥体的半径与其尖端的距离成线性关系。(否则它不是圆锥体!)

因此,如果圆锥体与屏幕平面相交时具有
初始半径
,则稍后:

radius(distance) = distance * initialRadius / focalDistance
您必须在每一步都重新计算该值,因为每一步都需要不同的距离

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

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


(或者更好的做法是,根本不使用距离。只使用深度,即仅垂直于屏幕平面的向量分量。如果将场景旋转到相机帧中,这可能是z轴或y轴。)

我会注意到像素通常是正方形,实际上圆锥体应该是平锥体。然后,大小是线性关系,然后距离,而不是指数。谢谢卢卡,好点!让我们把事情简化一点。为了在光线行进/球体跟踪的顶部实现圆锥体行进,我需要至少近似一个“合适的半径”,该半径“在安全方面是错误的”——圆锥体行进中发生的事情是将当前步长位置的“距离球体的大小”与“当前圆锥体宽度”进行比较。但是……暂时忽略整个径向圆锥体/像素球形圆盘近似,并考虑矩形“视锥台”。对于世界单位宽且投影到320px*320px屏幕单位的视图平面,距离t处的平截头体的总宽度应为t*w*tan(fovRadians*0.5),对吗?(…或乘以1/tan…或除以tan…或除以1/tan?:)对于fov=90°,则整个tan(或1/tan等)等于1,因此t*w。(现在宽度=高度。稍后取两者的最小值。)因此对于给定的像素p,整个向上缩放的视锥体在距离t处的矩形子部分为t*w/320。为了安全起见,我的圆锥体圆需要适合该矩形,但不能重叠,因此半径=min(PixelRectInfustumWidth,PixelRectInfustumHeight)/2。看到这个推理的任何问题了吗?“视觉测试”很棘手,因为我得到了一种或另一种混叠伪影,主要是在边缘,这让我认为我不应该使用“记录的最后一个圆锥体半径”作为正常ε。。。但这是另一天的另一个话题。现在我不完全确定是乘以还是除以fov/2的tan,还是除以它的1/tan。