全部专题

从一条射线到一个球:Ray Marching 的步长究竟怎么选?

固定步长可能跳过薄物体,也可能在空白区域浪费迭代。球面追踪按到表面的安全距离前进。球的 length(p)-r 是精确距离场;随意缩放或扭曲后的场则未必仍提供不会越过表面的距离下界。

先固定问题

固定步长容易跳过薄物体,也可能在空区域浪费大量迭代。Sphere tracing 的前提是距离场给出到表面的安全距离,因此可以按这个距离前进。示例球体的 length(p)-r 是精确 SDF,而被随意放大或扭曲的函数可能不再提供安全步长。

关键代码

float travel=0.0;
bool hit=false;
for(int i=0;i<80;i++){
  float distance=scene(origin+direction*travel);
  if(distance<0.002){hit=true;break;}
  travel+=max(distance,0.001);
  if(travel>12.0)break;
}
vec3 color=hit?shade(origin+direction*travel):background;

按顺序验证

先看球体,再看布尔凹槽。降低步数时检查漏掉的像素;扩大命中 epsilon 时检查轮廓膨胀。每次只改一个退出条件。

适用范围和常见错误

循环用尽不等于命中。远处没有命中也必须终止;法线与阴影只应在命中后求值。复杂分形还需要对应的距离估计推导。

继续实验

参考

官方文档

运行相关示例