Appearance
地面的重生
背景:地面系统有 3 条独立渲染路径(solid/grid/checker),维护成本高且各有 bug。ADR-091 决策统一为单一 canvas 路径。 过程:删除 GridMaterial 依赖 → 新增 _generateGroundTexture() → 512×512 canvas 统一绘制 → 所有 flat 样式走同一路径。
序
七月十二日,下午。
Riku 站在屏幕前,看着 env-impl.ts 的代码。345 行未提交的改动,像一团乱麻。
地面系统有三种样式:solid(纯色)、grid(网格)、checker(棋盘格)。每种样式一条独立的渲染路径。
"三条路径," Riku 对自己说,"三条路,三个坑。"
三条路
| 样式 | 技术路径 | 问题 |
|---|---|---|
| solid | StandardMaterial.diffuseColor | 无 |
| grid | GridMaterial(Babylon.js 独立 shader) | WebGL shader 编译延迟导致首次渲染变纯色;重启后才恢复 |
| checker | canvas 128×128 → toDataURL() → Texture → StandardMaterial | canvas 分辨率低、toDataURL 编码可能异步、常被 opacityTexture 遮挡导致不可见 |
"grid 的问题是 shader 编译延迟," Riku 对 Jieling 说,"第一次切换到 grid 样式,地面会变成纯色。要等 shader 编译完,重启应用才能恢复。"
"checker 的问题呢?"
"checker 的 canvas 只有 128×128 像素," Riku 说,"分辨率太低,棋盘格模糊。而且 toDataURL 是异步的,可能在渲染时还没准备好。"
"所以要统一?"
"对," Riku 说,"三条路合并成一条。"
统一
Riku 打开 ADR-091 的文档,标题是「地面纹理统一 —— 4 种样式合并为单一 canvas + StandardMaterial 路径」。
核心思路:所有 flat 样式都用 canvas 绘制纹理,然后作为 StandardMaterial.diffuseTexture 应用。
typescript
function _generateGroundTexture(state: GroundState, scene: Scene): Texture {
const canvas = document.createElement('canvas');
canvas.width = 512;
canvas.height = 512;
const ctx = canvas.getContext('2d')!;
// 根据 groundStyle 绘制
switch (state.groundStyle) {
case 'solid':
ctx.fillStyle = state.groundColor;
ctx.fillRect(0, 0, 512, 512);
break;
case 'grid':
ctx.fillStyle = state.groundColor;
ctx.fillRect(0, 0, 512, 512);
ctx.strokeStyle = state.groundLineColor;
ctx.lineWidth = 2;
// 画网格
for (let i = 0; i <= 512; i += state.tileSize) {
ctx.beginPath();
ctx.moveTo(i, 0);
ctx.lineTo(i, 512);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(0, i);
ctx.lineTo(512, i);
ctx.stroke();
}
break;
case 'checker':
// 画棋盘格
break;
}
const texture = new Texture(canvas.toDataURL(), scene);
return texture;
}"512×512 像素," Riku 说,"比 checker 的 128×128 清晰四倍。"
"GridMaterial 呢?" Jieling 问。
"删掉," Riku 说,"不再需要。GridMaterial 是 Babylon.js 的独立 shader,编译慢,还有延迟问题。用 canvas 画网格,效果一样,没有 shader 编译问题。"
删除
Riku 打开 package.json,删除了 @babylonjs/materials 依赖。
"这个包只提供 GridMaterial," 他说,"删掉它,bundle 体积减小 50KB。"
他跑了一遍构建。通过。
打开应用,切换到 grid 样式。地面立刻显示网格,没有延迟。
"现在呢?"
"现在它即时生效。"
尾声
Riku 提交了代码。
feat: 地面纹理统一(ADR-091)— 删除 GridMaterial,所有 flat 样式走 canvas 路径他站在窗边,看着远处的天际线。七月的阳光已经落下去了,路灯一盏一盏亮起来。
地面从三条路变成了一条路。路变宽了,坑填平了。
"地面是城市的地基," Riku 对自己说,"地基稳了,城市才能站稳。"
教训:渲染路径不是越多越好。三条独立路径意味着三倍的维护成本、三倍的 bug 概率。统一为一条路径,用 canvas 绘制所有样式,是最简单、最可靠的方案。