{
  "lead": "曼德博球是曼德博集合在三维空间中的推广。它没有由三角形组成的模型，形状完全由一个数学公式定义，每个像素通过「光线步进」直接从公式计算出来。",
  "formulas": [
    [
      "DE = 0.5 · r · ln r / dr",
      "dr = 8 · r⁷ · dr + 1"
    ]
  ],
  "terms": [
    [
      "三维迭代公式",
      "把点转换成球坐标 <span class=\"explain-math\">(r, θ, φ)</span>，做 8 次幂运算 <span class=\"explain-math\">r⁸ · (sin 8θ cos 8φ, sin 8θ sin 8φ, cos 8θ)</span> 后加回原点坐标，相当于 <code>z² + c</code> 的三维版本。"
    ],
    [
      "距离估计",
      "在迭代的同时计算导数 <code>dr = 8 · r⁷ · dr + 1</code>，得到当前点到分形表面距离的下界估计 <code>DE = 0.5 · r · ln r / dr</code>。"
    ],
    [
      "球体追踪（Sphere Tracing）",
      "从相机向每个像素发出一条光线。每一步都安全地前进 DE 的距离，因为这么远的范围内一定没有表面。当距离小于 <code>0.001 × 已行进距离</code> 时视为击中表面；超过 40 步或行进超过 10 个单位则视为没有击中，画成背景。"
    ],
    [
      "光照",
      "在击中点附近沿 x、y、z 三个方向做中心差分，求 DE 的梯度作为表面法线，再与固定的光照方向做点积，加上环境光，得到明暗。"
    ],
    [
      "相机旋转",
      "拖拽改变旋转角度，用 Z·X·Y 旋转矩阵把视线方向变换到世界坐标。"
    ]
  ],
  "flow": [
    [
      "js",
      "JS 处理拖拽和滚轮，更新旋转角度与缩放。"
    ],
    [
      "rust",
      "JS 调用 <code>raymarch(400, 400, rx, ry, rz, 缩放, 40)</code>。Rust 在 CPU 上为 16 万个像素逐一做光线步进，返回 RGBA 像素数组。"
    ],
    [
      "js",
      "JS 用 <code>texImage2D()</code> 把像素上传为 WebGL 纹理，画一个铺满画布的矩形来显示它。"
    ]
  ],
  "flow_notes": [
    "注意：这里 WebGL 只负责显示，所有三维计算都由 Rust/WASM 在 CPU 上完成。页面加载时会先检测 WebGL 环境，检测结果显示在画布下方。"
  ],
  "perf": [
    "每条光线最多 40 步，每一步都要做一次 8 轮迭代的距离估计，击中后还要额外算 6 次来求法线，计算量很大。底部显示的就是单帧耗时。",
    "只在视角变化时重新计算（<code>needsRender</code> 标记加 <code>requestAnimationFrame</code> 合并），静止时不占用 CPU。"
  ],
  "src": [
    [
      "crates/graphics/mandelbulb/src/lib.rs",
      ""
    ],
    [
      "www/mandelbulb/index.js",
      ""
    ]
  ]
}
