




















#光线追踪 #球体追踪
参考:
《The Unity Shader Bible》

光线从摄像机出发,穿过像素点,直到击中表面以达到目标。这个概念被称为“光线投射(Ray Marching)” ,即沿着光线找到最近物体的过程,因此得名“球面追踪(Sphere Tracing)”。 RayMarching就是光线行进,从摄像机向屏幕上的每一个像素发射一条光线,光线按照一定步长前进,检测当前光线距离物体表面的距离,并且根据这个距离调整光线的步长,直到抵达物体表面。
我们需要根据即将生成的曲面形状来确定射线的终点。在此场景中,这类名为SDF(有符号距离函数)的函数会以点为输入,返回该点与图形表面之间的最短距离。若返回值为正,则射线继续前进;若返回值为零,则射线将与曲面发生碰撞。
为了正确使用该技术,我们需要在着色器中定义至少两个函数。为此,需要考虑以下因素: • 一个用于确定曲面类型的sdf函数. • 另一个用于计算球体追踪的函数.

是
否
是
否
起点 ray_origin
计算 ray_position
调用 planeSDF ray_position
得到最近距离 d
distance_origin += d
d < SURFACE_DISTANCE?
命中物体 结束
distance_origin > MAX_MARCHING_STEPS?
未命中 空
球体追踪就是用场景的 SDF(signed distance function)告诉你从当前位置到最近表面的最小距离,然后用这个距离作为步长向前跳——仿佛每一步放一个贴紧场景的球体,球体刚好不穿透物体,直到球体接触表面或超过上限。
“射线起始点”向量对应“射线的起点”,即相机在局部空间中的位置;而“射线方向”则等于“网格顶点的位置”,也就是我们正在处理的球体所在位置。由于我们需要根据边生成图元划分,因此必须确保sdf平面的位置与三维物体的位置保持一致。 💁在该示例中,相机到平面的距离即float plane = ray_position.y - _Edge; 为射线步进的长度 
这段代码是一个 Sphere Tracing(球面追踪 / Ray Marching) 的核心片段,用来做 基于 SDF(有符号距离函数) 的光线行进算法。我们逐行拆解:
ray_origin
光线的起点(比如相机位置)。
ray_direction
光线的方向(归一化向量)。
distance_origin
当前光线走了多远。
planeSDF(ray_position)
Sphere Tracing 原理
因为 SDF 告诉我们“离物体最近的距离”,所以每次可以大胆走这么远,而不会穿过物体。
这就像拿着一个“安全半径球”在前进,保证不会撞墙。
计算当前位置:
计算到物体的最近距离:
向前走这么远:
收敛条件:
distance_scene < SURFACE_DISTANCE,说明非常接近表面,可以认为击中了物体。distance_origin > MAX_MARCHING_STEPS,说明走太远还没碰到 → 判定为空。想象你在 漆黑的房间里摸墙:
如前所述,需要剔除球体平面上的像素点。要实现这种评估,我们需要获取球体y轴上顶点在物体空间中的坐标位置。通过使用“discard”语句,我们可以剔除位于边缘的像素点,具体操作如下所示。


我们可以将球体的像素投影到其背面,对于平面,可以使用sv_isfrontface语义将其投影到正面。

在这种情况下,如果要在sdf平面上投影纹理,就需要考虑sdf平面背面的位置和方向——记住这个平面是朝向正y轴的。因此,纹理的方向需要与之相反。 
为此,我们可以使用点“p.xz.”计算最大球面投射区域内的uv坐标。 
⚛交点局部坐标映射为UV坐标

进一步,将UV居中
_Edge=0.43

_Edge=0.02 
让UV适配球体
修改边属性值后,我们将看到平面的纹理投影会根据球体的体积而逐渐减小。




此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。