不用3D编辑器造世界:World of ClaudeCraft运行时程序化生成地形与VFX实现原理
【免费下载链接】world-of-claudecraft项目地址: https://gitcode.com/gh_mirrors/wo/world-of-claudecraft
World of ClaudeCraft 是一款经典风格的微MMO,但它最"反直觉"的地方在于:整个游戏世界的地形、贴图、技能特效(VFX)几乎都不是美术在 3D 编辑器里手工摆出来的,而是由 TypeScript 代码在运行时程序化生成(procedural generation)出来的。本文将带你从零了解它如何用一套确定性噪声算法造出起伏的山脉与海岸,如何用 Canvas 在内存里"画"出地形贴图,又是如何用粒子池和声明式特效规格做出华丽的技能 VFX——全程无需一个 DCC 建模工具。
一、整体架构:先看懂"为什么可以不用编辑器"
World of ClaudeCraft 采用三层结构,程序化生成的前提正是这种分离:
| 层 | 路径 | 职责 |
|---|---|---|
| 确定性模拟核心 | src/sim/ | 无 DOM、无 Three.js 依赖,浏览器/服务端/无头环境跑的是同一份代码 |
| Three.js 渲染层 | src/render/ | 只读世界状态并绘制,程序化几何/贴图/VFX 都在这 |
| 客户端交互 | src/game/ | 输入、相机、音效 |
关键点:地形高度只由数学函数定义,不存在任何"高度图文件"。同一组坐标 + 同一随机种子,在客户端、服务器、强化学习无头环境里算出的高度逐位一致——碰撞、寻路、渲染因此永远不会"各画各的"。这正是它敢完全放弃 3D 编辑器的底气。
📌 渲染层有一条硬不变量:必须直接采样模拟核心的高度函数,绝不在渲染端重新推导高度(见 src/render/CLAUDE.md "Terrain height = sim height" 一节)。
二、程序化地形生成:一个函数造出整个世界
2.1 高度场的噪声叠加
打开 src/sim/world.ts,核心入口只有两行:
terrainHeight(x, z, seed) = applyTerrainPads(x, z, seed, terrainHeightUnpadded(x, z, seed))terrainHeightUnpadded内部是一组自下而上的噪声层(baseHeight,src/sim/world.ts#L3355):
- 丘陵层:低频率 FBM(分形布朗运动)噪声,坐标先经过一次"域扭曲"(domain warp),让等高线自然蜿蜒;
- 峭壁层:Ridged-multifractal(山脊分形)噪声生成尖锐山脊,并用"高地遮罩"限制它只从丘陵隆起处生长——低地永远不会突然冒出一座刺;
- 细节层:更高频率的 FBM,湿地的振幅平滑如镜,山地则更粗粝;
- 城镇平地:每个区域中心的定居点被压平为高原,保证建筑稳站;
- 人工垫高链(
applyTerrainPads):城堡花园、码头台阶、湖心岛等"手工微调",全部用 smoothstep 平滑混合,而不是硬切。
2.2 从高度函数到网格:分块 LOD 渲染
渲染端 src/render/terrain.ts 把 360×1080 的世界条带切成约 60 单位的网格块(chunk),每个块独立做视锥剔除:
- LOD 按距离分级:城镇附近顶点密集,荒野则粗糙——远处不需要那么密;
- 裙边(skirt):每个块边缘向下垂一小片,遮住 LOD 交界处经典的"裂缝";
- 顶点级 splat 混合:草/泥/岩石/沙的权重按坡度、海拔、离路距离预先算好,写进顶点属性,着色器里实时混合,无需美术刷贴图权重;
- 宏观法线贴图:由网格自身的高度反烘焙(src/render/terrain_mesh_height.ts),远看也有真实凹凸感。
更远的地方则由 src/render/far_terrain.ts 接管:一整块粗粒度的"远景全景网格",十几个可剔除的 tile 就画出了到世界边缘的完整地平线,每帧开销仅一次可见性循环。
三、连贴图都不需要图片文件:运行时 Canvas 生成
传统项目的美术资源目录里塞满 PNG,而 src/render/textures.ts 头注释写得很直白:"Procedurally generated canvas textures — no external assets."(程序化生成的画布贴图——无外部资源)。
实现原理很简单:
- 一个
makeCanvas辅助函数创建document.createElement('canvas'),用 2D 上下文画完再包成THREE.CanvasTexture; - 比如
groundDetailTexture():在 256×256 上画 5000 个半透明噪点 + 1400 根草叶线条,作为地形顶点色的细节乘层; - 随机数用的是自实现的种子 LCG(
rnd(),初始种子 12345),而不是Math.random——保证每次启动生成的贴图逐像素一致,可复现、可测试。
也就是说,"贴图"这一整个资产类别被一段 50 行的绘制函数替代了。模型类资产才走 GLB 通道(含 AI 图生 GLB 的管线,见 docs/image-to-glb-asset-workflow.md),而纹理基本全部运行时程序化生成。
四、VFX 实现:粒子池 + 声明式特效规格
4.1 一颗"粒子云"打天下
技能与氛围粒子系统的核心在 src/render/vfx.ts,设计取舍非常克制:
- 单一对象池:全部粒子装进一个
THREE.Points云,加色混合(additive blending)一次绘制完成,不逐粒子建对象; - 精灵图集:火焰、火花、魔法光晕、烟雾取自 Kenney CC0 粒子包的 4×4 图集,启动时加载一次;
- HDR 泛光:在合成器档位上,粒子颜色被推到 1.0 以上,HalfFloat 目标使其自然泛光(bloom),核心更亮、拖尾更炫;
- 投射物即轻量发射器:追踪目标、命中即爆裂,逻辑极薄。
4.2 声明式规格:新增一个技能特效不写渲染器
普通技能特效不再手写渲染模块,而是往声明式规格表里加一条数据,注册进 src/render/ability_vfx_registry.ts,由池化引擎播放。项目里能看到大量此类规格模块,例如:
- 毁灭系:destruction_vfx_specs.ts
- 死灵系:necromancy_vfx_specs.ts
- 德鲁伊系:druid_vfx_specs.ts
- 圣骑士法系:paladin_spell_vfx.ts
4.3 地面特效的"楼层规则"
贴地 VFX 最容易出现谁盖住谁的渲染错乱。World of ClaudeCraft 用 floor_vfx_layer_core.ts 定义了一个 renderOrder 楼层阶梯:ground(世界自身印记)→player(玩家技能地面特效)→encounter(Boss 预警圈、危险区)→reticle(瞄准辅助)自下而上。玩家必须反应的机制永远画在玩家自己释放的特效之上——这是一条用策略代码固化下来的视觉优先级规则,而非魔法数字。
五、性能预算:程序化的代价谁来付
程序化生成把"资产制作"成本移到了运行时,因此渲染层对 GPU 工作有严格调度(见 src/render/CLAUDE.md "GPU work" 一节):
- 预热清单:进入世界前按清单条目异步编译着色器,首帧不卡顿;
- 后台 GPU 队列:所有离屏构建工作走统一的
background_gpu_queue.ts,按帧预算分片执行; - 分块驻留策略:chunk_residency_core.ts 决定"相机能看多远才会碰到未构建的地面",与远景雾联动。
六、总结:程序化生成给了它什么
| 维度 | 传统管线 | World of ClaudeCraft |
|---|---|---|
| 地形 | 美术在编辑器里雕刻并导出高度图 | 一个确定性噪声函数 + 垫高链,服务器/客户端/RL 环境共用 |
| 贴图 | 美术输出 PNG 序列 | 运行时 Canvas 绘制 + 种子随机,零图片文件 |
| 技能特效 | 逐技能搭粒子系统 | 声明式规格 + 单粒子池 + 楼层规则 |
| 资产体积 | GB 级资源包 | 大量几何与贴图"代码即资产",体积大幅压缩 |
| 可复现性 | 依赖文件哈希 | 同种子 = 同世界,天然支持无头强化学习环境 |
如果你想动手验证,本地跑npm run dev后观察地形分块加载,或阅读 tests/ 中terrain相关用例——确定性意味着这些生成逻辑都有纯 Node 测试护航。这套"代码即世界"的思路,对任何想用最少美术资产做 MMO 或大世界的开发者,都是一份相当完整的参考实现。
【免费下载链接】world-of-claudecraft项目地址: https://gitcode.com/gh_mirrors/wo/world-of-claudecraft
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考