Appearance
地面系统
系统概览
地面子系统的完整实现:纯色/纹理/程序化纹理三种地面模式,支持 PBR 材质(ADR-114)、边缘淡出、UV 滚动动画、地面涟漪(与水系统联动)、程序化纹理含 6 种预设(木材/大理石/混凝土/瓷砖/地毯/金属),每类含 albedo、roughness、normal 三通道生成器。预设数据已拆分至独立文件。
核心职责
env-ground.ts— 地面调度与资源生命周期:applyGround的原地/重建两条路径分派、程序化纹理生成器注册表、材质属性同步原语(_sync*)、涟漪贴图挂载/摘除、高度查询。材质「长什么样」的决策已上移至env-ground-spec,本模块只负责执行与释放(ADR-226)。env-ground-presets.ts— 地面预设类型定义(GroundPreset)、7 套内置预设(GROUND_PRESETS)、buildGroundPresetEnvState映射函数。经env-ground.tsbarrel re-export 保持向后兼容。
对外 API(节选)
GroundProceduralKind— 6 种程序化纹理枚举类型(定义位于env-ground-presets.ts)。GroundPreset/GROUND_PRESETS— 地面预设接口与内置预设集合(定义位于env-ground-presets.ts,经env-ground.tsre-export)。applyGround(state)— 根据 EnvState 应用地面材质/纹理/模式。以specKey(buildGroundMaterialSpec(state))与_currentGroundKey比对决定原地或重建,两条路径分别委派applyGroundMaterialSpec/createGroundMeshFromSpec。tickGround(dt)— 每帧更新地面 UV 滚动动画。getGroundHeightAt(x, z)— 查询地面高度(含倾斜平面插值,供模型/摄像机站立)。clearGroundTexCache()— 清理程序化纹理缓存。setOnTerrainReady(cb)/setOnGroundChanged(cb)— 地形就绪/地面变化回调。buildGroundPresetEnvState(preset)— 从预设构建部分 EnvState(定义位于env-ground-presets.ts,经env-ground.tsre-export)。disposeGround()— 释放地面材质、网格、反射与涟漪资源。_effectiveRoughness(state)/_effectiveBumpLevel(state)— 根据状态计算有效粗糙度/凹凸强度。_disableGroundRippleTexture(mat)— 禁用地面涟漪贴图。
与其他子系统关系
- 依赖
env-ground-spec的GroundMaterialSpec单源:specKey判定重建、applyGroundMaterialSpec落原地材质、createGroundMeshFromSpec建网格。三种几何(flat/infinite/terrain)无一例外(ADR-226)。 - 依赖
env-terrain的 FBM 噪声与高度图生成;createHeightmapGround/applyTerrainMaterial现由env-ground-spec.ts直接 import,env-ground.ts不再引用。 - 依赖
env-texture的统一 canvas 贴图工厂。 - 依赖
env-reflection的平面反射质量预设。 - 依赖
env-context的上下文与环境系统引用。 - 地面涟漪与水系统(
env-water)联动:涟漪纹理groundRippleTex由env-water-fx.ts的_groundRippleTex持有,地面侧仅通过_syncGroundRippleTexture/_disableGroundRippleTexture挂载与摘除。
不变量
- 地面重建路径(含 terrain)统一走
createGroundMeshFromSpec,原地路径统一走applyGroundMaterialSpec;_applyGroundInplaceLegacy与 terrain 专属重建分支已删除,terrain 不再有 legacy 特例(ADR-226 Phase 4)。 groundRippleTex的所有权归env-water-fx.ts(_groundRippleTex,经disposeGroundRipples释放)。disposeGroundMaterial的disposeTex跳过该名字的纹理,且mat.bumpTexture?.name === 'groundRippleTex'时先置 null 再 dispose 材质——地面侧只脱离不释放。applyGround重建路径必须复位_groundRipples = null与_groundRippleApplied = false,避免_disableGroundRippleTexture把上一代材质的陈旧 bump 恢复到新材质上。_disableGroundRippleTexture仅以_groundRippleApplied门控,不得对_groundRipples判空:暂存的原始 bump 本就可能是 null,null 也必须恢复(即恢复为「无 bump」)。- 高程着色(
groundType === 'terrain' && groundElevationColoringEnabled)由applyTerrainMaterial全权负责,applyGroundMaterialSpec的isElevation守卫跳过 albedo 来源、法线同步与涟漪 sync/disable,spec 侧不得覆盖。
菜单入口(去哪找 UI)
- 菜单层文件:
frontend/src/menus/env-ground-levels.ts,入口函数buildGroundLevel(): PopupLevel。 - 路由归属:场景菜单(
scene-menu.ts),target =scene:ground(注意文件名前缀env-与路由域scene:名实错位,历史遗留)。 - schema 节点 id 以
env:ground:*为前缀(如env:ground:presets/env:ground:texture/env:ground:overlay)。 - 添加/修改地面菜单行的规范流程见 menu-how-to.md。
UI 入口
- 菜单层级 / 入口函数 / 快捷键统一由 menu-map.md 机器生成(勿手改)。
- 运行时动态生成的菜单项(renderCustom / slideRow 等)无法静态提取,缺口由本卡正文说明。