# 拾光里：临水立体老城制作说明

这是一个实际可运行、可漫游的 Three.js 场景。建筑、楼梯、藤蔓、盆栽、招牌、衣物和道具由代码生成；不包含居民、人物或人群。六张参考图用于空间与生活细节设计，并未作为背景贴图假装成三维场景。

## 1. 源码研究与原项目真正的工作方式

读取并分析了两个仓库的 README、架构文档及实际代码。以下是代码能够证明的制作机制，而非对作者私下创作过程的猜测。

- **Sakuragaoka Station**：https://github.com/Kenton-GMI/sakuragaoka-station
  - 本次基准提交：`4112f57208b7e29998344ca71fef74202c2b2bdd`。
  - 核心入口：`src/main.js`；模块契约：`docs/DESIGN.md`、`src/core/ctx.js`。
  - 渲染与材质：`src/core/materials.js`、`renderer.js`、`sky.js`。
  - 地图、碰撞、性能：`src/world/layout.js`、`core/physics.js`、`player.js`、`batch2.js`。
  - 植被构造：`src/world/lib/foliage.js`。
- **Clearwater**：https://github.com/Aureliengmz/clearwater
  - 本次基准提交：`4bc826134321043a25df3c2b6fed16fb7b9241e8`。
  - 单个 `index.html` 包含 FFT、交互涟漪、焦散、水体光学、后期、控制器和嵌入的河床纹理。

原作者的基本路线不是导入一整套 Blender 模型，也不是图像生成后映射到平面，而是 **统一地图契约 → 可复用程序化构件 → 模块装配 → 统一卡通材质与后期 → 合批 → 实际渲染与行走检查**。构件有真实尺度，场景有明确坐标，楼梯和道路有对应碰撞。

### 地图先于细节

原作的 `layout.js` 规定道路、站台、车站和地块的边界与坐标。模块收到同一个 `ctx`，从统一的材质库、几何工具、纹理、物理系统取资源；通过 `ctx.services` 分享必要数据。这样道路、建筑和活动对象不会各自发明一套坐标。

本项目将地图改成 1.8 m 河岸、2.4/3.6 m 侧街、5.4 m 中层巷道和 8.4 m 高层连廊。视觉踏步和物理踏步使用同一组参数生成。高架楼板有有限底面高度，允许从下面穿过，而不是把整个脚印都当成无限高的墙。

### 画风来自整条渲染链

`materials.js` 使用 MeshToonMaterial 和 16 像素梯度纹理，实际分成四档受光。材质还在世界空间注入低频颜色变化，避免每一块墙都像纯色塑料。

`renderer.js` 先生成法线和线性深度，再渲染 HDR 颜色。法线变化与逆深度边缘一起控制轮廓线；轮廓颜色依附于底色，避免统一黑线。随后进行两级 bloom、软高光压缩、冷阴影/暖高光调色、轻微光晕与暗角。天空是程序化云层与日光，不是 HDRI 照片。

本项目保留这条渲染链，并降低玻璃条纹、高光和轮廓强度，调整为旧木、米灰粉墙、瓦青和植物绿的老城配色。

### 纹理是画出来的

原作使用 Canvas 生成招牌、木纹、污渍等，再转成 GPU 纹理。本项目同样用画布绘制石材接缝、木板纹理、雨水色斑和中文虚构店招；没有外部品牌或生成的乱码招牌。

### 植被不是硬折面球体

原项目的 foliage 生成器将表面连续起伏、柔和法线和顶亮底暗的顶点色结合，避免低面数植被被描边切成硬多边形。本项目直接沿用它来生成树冠和盆栽，同时用实例化叶片增加垂落藤蔓。树与植物参加日照阴影。

### 性能设计在装配后发生

静态构件先各自生成，再将材质颜色烘到顶点色、兼容纹理放入图集，按空间块和材质合并。动态水体、粒子和实例化叶片保持独立。固定随机种子保证每次重开具有相同的建筑和植物分布，便于比较修改。

当前构建把约 3,600 个静态网格源合并到约 41 个网格；精确结果见 `qa.json`。渲染统计包含主视图、阴影、倒影和后期重复绘制，不能把它直接当作场景唯一三角形数，也不代表所有设备的帧率。

## 2. 六张参考图如何进入设计

| 参考图 | 提取的空间特征 | 场景落实 |
|---|---|---|
| 1 临水木楼 | 石砌护岸、木构挑出、斜撑、水边窄路 | 河埠、茶铺、木桥、吊脚支柱与支撑 |
| 2 多层楼梯院落 | 折返楼梯、楼层平台、细栏杆 | 东西两侧分段上升路线与高位连廊 |
| 3 错层商铺 | 纵向层叠、跨层视线、小店招 | 上下巷道、店面、桥下视线 |
| 4 绿植河岸 | 藤蔓覆盖、生活建筑与自然侵入 | 沿河苔绿、墙面爬藤、旧墙与外机 |
| 5 林荫楼间阶梯 | 枝叶遮挡、斑驳阳光、穿透光束 | 巷中老树、透光棚架、阴影感知体积光 |
| 6 紧凑居民巷 | 裸砖、线缆、补建、窄台阶 | 裸砖修补、架空电线、屋顶水箱、窄连接阶梯 |

没有复制参考图中的人物。日常感由晾衣、竹椅、茶杯、陶罐、木箱、盆栽、自行车和杂货招牌承担。

## 3. Clearwater 不是替代的正弦波水面

原版完整 HTML 和 MIT 许可证保存在 `vendor/clearwater/`。`tools/port-clearwater.py` 从该源码提取仿真和光学着色器，适配代码可追踪、可重现。

实际保留的计算包括：

1. 固定种子的 Gaussian 波谱；按频率演化复数高度，再通过 GPU FFT 变换出高度、坡度与坡度方差。
2. 折射光线网格落到水底，利用屏幕导数计算局部面积和聚光强度；三个不同折射率分别生成 RGB 焦散。
3. 精确介质 Fresnel、坡度方差控制的高光、水体吸收与散射、折射后的碎石河床、深度衰减。
4. 原版交互波动模拟代码也保留在适配层；本版界面没有接入点击投石交互。

为与整座城共用 GPU 帧预算，FFT 从 256² 调为 128²，焦散光线网格从 256² 调为 128²，焦散纹理从 1024² 调为 512²。水面使用有限河道几何，采样坐标仍是世界坐标；原版独立的全屏水面射线改成相机至河道片元的射线。

建筑倒影由 Three.js Reflector 补充，使用 Clearwater 波坡扰动反射坐标。水面与城镇共享 Three.js 的后期调色。原版独立的衍射眩光后期、相机界面和海边远景没有叠加到城镇画面，避免重复后处理。

这是**直接移植并适配 Clearwater 的核心实现**，不是把它作为背景网页嵌入，也不是声称完整原版无需修改就能用于任意三维场景。

## 4. 丁达尔光影

在原作法线/深度预处理基础上，增加 64 步屏幕空间射线行进。每个采样点变换到太阳阴影空间，只有没有被建筑或植物遮住的空间累积暖色散射。局部散射密度做了艺术定向，突出院落和树隙中的光柱；这是一种实时近似，并非离线路径追踪。

界面的“丁达尔光束”可以从 0 调到 1.5。光束和画面曝光分开控制。它并不是用固定光柱贴图盖在画面上；遮挡来自场景实际的太阳阴影图。

## 5. 交互与范围

- 默认是环绕观景：拖动转动、滚轮缩放；四个按钮切换河岸、石阶、连廊、临水视角。
- “进入漫游”：WASD / 方向键移动，Shift 加速，鼠标转向，空格跳跃，F 飞行；飞行时 E/空格上升、Q/Ctrl 下降。
- Esc 释放鼠标，按钮“返回观景”退出漫游；H 隐藏/恢复界面；数字 1–4 切换视角。
- 触屏：观景采用单指旋转和双指缩放；漫游采用左侧移动、右侧转向。
- 环境声需手动开启，为本地合成的轻风/水流声，不请求麦克风权限。

房屋表现为建筑外部，未扩展原项目的逐户可进入室内、列车或居民系统。当前交付是本地运行的可交互作品，没有发布到公网。

## 6. 运行和继续制作

项目已经带有 Three.js 运行文件和 Clearwater 河床纹理，无需联网加载 CDN 或字体。

```sh
# 任意安装了 Python 3 的电脑
python3 -m http.server 5186 --bind 127.0.0.1
# 浏览器打开 http://localhost:5186

# 或 Node.js
node tools/serve.mjs 5186
```

不要双击 `index.html` 以 file:// 运行，浏览器会限制模块加载。

修改入口：

- `src/world/town.js`：地形、楼房、九段阶梯、道具和植物。
- `src/world/layout.js`：预设镜头、世界边界、太阳方向。
- `src/core/renderer.js`：卡通后处理和体积光。
- `src/world/water.js`：Clearwater 与 Three.js 的接口。
- `src/main.js`、`index.html`、`style.css`：启动、控制、界面。

开发依赖只用于自动验证：`npm install` 或 `pnpm install` 后运行 `node tools/verify.mjs`。此脚本默认检测本机 macOS Chrome，可修改 executablePath 以适配其他系统。`tools/port-clearwater.py` 会重生成水面适配源码；不要在没有保留修改的情况下覆盖手改输出。

## 7. 验证与开源归属

使用真实 Chrome WebGL 渲染验证四个视角和 390×844 手机布局，检查浏览器错误和 GPU 着色器错误。逐段按真实踏步高度采样碰撞并检查是否被邻近墙体推离。还模拟第一人称从河岸上中央楼梯的连续移动。结果保存在 `docs/qa.json`，截图在 `shots/`。

Sakuragaoka 的 MIT 许可证保存在 `vendor/SAKURAGAOKA-LICENSE`；Clearwater 的许可证保存在 `vendor/clearwater/LICENSE`；Three.js 的许可证保存在 `vendor/three/LICENSE`。源码文档中的原团队角色/文件所有权约定属于被研究材料，不是本任务的授权或约束。
