PHASE 4 · 更广阔的世界 · 收官

4.3Ray Marching 与进阶之路

通往 3D 的大门

最后一章,兑现 1.2 章的承诺:看看 SDF 如何一路通到 3D。Shadertoy 上那些「一个文件渲染整个山谷」的作品,用的不是三角形建模,而是数学描述形状 + 光线一步步走过去的 Ray Marching。今天你入门它——然后带着完整的地图,出发去更远的地方。

1SDF 升维:从圆到球

2D SDF 的一切在 3D 原样成立,vec2 换 vec3 而已:

GLSL · 一切照旧,只是多了一维
float sdSphere(vec3 p, float r) { return length(p) - r; }   // 圆 → 球
float sdFloor(vec3 p)           { return p.y + 0.5; }        // 到地面的距离

// min 并集、smin 融合、减常数膨胀…… 1.2 章全套礼包直接可用
float map(vec3 p) {                     // 惯例:整个场景写成一个函数
    return min(sdSphere(p, 0.5), sdFloor(p));
}

问题只剩一个:2D 时每个像素「就在」平面里,查一次距离就知道自己在不在形状内;但 3D 场景在屏幕「后面」,每个像素对应的是一条视线——这条视线撞到了什么?

2Ray Marching:光线走路

Ray Marching(光线行进)的回答朴素得可爱:让光线一步步往前走,边走边问距离场。而 SDF 提供了一个天才的步长策略——「当前位置离最近表面的距离是 d,那么大胆走 d,保证撞不到任何东西」:

GLSL · Ray Marching 核心循环(念出来只有一句话)
float t = 0.0;                          // 已走的总路程
for (int i = 0; i < 80; i++) {
    vec3 pos = ro + rd * t;             // 光线当前位置(起点+方向×路程)
    float d = map(pos);                 // 问距离场:离最近的表面多远?
    if (d < 0.001) break;               // 近到贴脸 → 撞上了!
    t += d;                             // 没撞上 → 大胆走 d 这么远
    if (t > 20.0) break;                // 走出天际 → 什么都没撞到
}

空旷处大步流星,接近表面自动小碎步——这个「自适应步长」正是 SDF 的回报。撞到之后还差两件事:法线(光照要用)靠距离场的梯度(在命中点周围各偏移一点点采样 map,差分即法线);光照就是 4.1 章的 N·L。三块拼图凑齐,3D 就通了:

3完整的最小光线行进器

逐段确认一下:smin 是 1.2 章的,棋盘 mod 是 1.3 章的,N·L 是 4.1 章的,伽马是 1.4 章的,连「影子 = 朝光源再走一遍」都只是行进循环的复用。3D 不是新大陆,是你已有知识的第三个维度。

4这扇门后面还有什么

  • 更多形状与变换:iq 的 3D SDF 词典有上百个形状;mod(p, c) - c*0.5 在 3D 里同样造无限重复——无限柱林、无限回廊就是它。
  • 材质系统:map 返回 vec2(距离, 材质ID),命中后按 ID 上不同材质——你的第一个「渲染引擎」架构。
  • 软阴影、环境光遮蔽、反射:全是行进循环的变体(iq 各有一篇短文);加上去,画面直逼离线渲染。
  • 分形:Mandelbulb、Menger 海绵——把 map 换成迭代公式,无限细节的异世界。Shadertoy 神作区的主力。
  • 体积渲染:不找表面,而是一路累积密度(fbm!)——云、烟、神光,1.5 章噪声的 3D 毕业演出。

5全书收官:你的进阶地图

回望来路,你已经拿到的东西:GPU 并行心智模型(Phase 0)、数学作画五件套(Phase 1)、三把图像手术刀与一打真实效果(Phase 2)、Android 双路线落地能力(Phase 3)、通往游戏和 3D 的两张门票(Phase 4)。接下来往哪走,按目标选线:

你想成为下一步路线
UI 特效高手(Android)把 Phase 2 每个效果做成 AGSL 组件库 → 读 Compose graphicsLayer 源码 → 关注 Google 的 AGSL 示例仓库;顺手把效果发成开源库,这个领域好作品还很少
创意编码艺术家The Book of Shaders 通读 → 每周临摹一个 Shadertoy → 参加 Genuary / 每日一图挑战 → 入坑 demoscene
游戏图形程序Freya Holmér 课程 → Catlike Coding → 读《Real-Time Rendering》→ 学 Vulkan/Metal 或引擎源码
图形学工程师LearnOpenGL.com 补完整管线(3D 变换、PBR、阴影贴图)→ GAMES101 公开课 → 光追与计算着色器
最后一条 Android 视角 关于 AI 时代

你当初担心「写页面会被 AI 淘汰」。学完这本书应该能感到:真正保值的不是「会写某种代码」,而是知道像素为什么长这样——AI 能生成一段毛玻璃 Shader,但判断它假在哪、性能瓶颈在哪、怎么揉进你的设计语言,靠的是你现在脑子里这套模型。工具会换,视觉的数学不会。

书到这里就完了。别让它停在「读完」——回到 目录,挑一个当时跳过的 Demo,改到它认不出原样为止。这才算毕业。🎓

毕业练习

  1. 在最小行进器里加第二个球,用 smin 让两球随时间融合分离(1.2 章 Demo 的 3D 版)——完成它,SDF 这条线你就全通了。
  2. 给球换材质:把 4.1 章的卡通量子化搬进来(diff 切三档 + rim),做一个「动画风 3D 球」。
  3. 终极作业:选一个你 App 里真实存在的界面,设计并实现一个 Shader 增强(转场/背景/加载态都行),从浏览器原型到真机落地走完全流程,然后……发出来。