主题
离散瓦片地形自定义地表纹理
离散瓦片地形可以使用项目自己的颜色纹理。同一场景不绑定单一风格:内置风格、混合风格和项目自定义风格可以共同涂抹同一张地图。
编辑器通过公开入口生成旧客户端能够读取的项目资源。用户不需要从 Update 目录复制或解密内置 Material、config_v1.json 和 TextureStyle;这些下载资源可能使用 TNND 包装,编辑器会通过 ResourceCache 在内存中读取。
最快工作流
- 把颜色图片及可选的
_mix、normal、roughness、metallic 放在同一目录。BaseColor 支持 PNG、JPG、TGA 和 DDS;辅助图支持 PNG、JPG、TGA,packed_mix必须使用保留四通道的 PNG 或 TGA。 - 打开离散瓦片地形场景,在“地表”中先选择一个现有纹理。它会作为新纹理的表面细节模板。
- 选择“UV旋转”。默认
90°用于补偿默认镜头相对地形世界方向旋转了90度;图片已经按地形世界方向制作时选择0°,方向相反时选择270°。 - 点击“添加项目纹理”,选择自己的颜色图片。
- 等待编辑器完成预检、合并和项目文件替换。
- 在“地表风格”中选择“项目自定义地表”,再选择新纹理涂抹。
- 执行 Undo/Redo,保存并重开场景,最后进入调试运行确认效果。
添加时,颜色来自用户图片。编辑器优先直接采用显式或同目录发现的 packed _mix;否则自动发现独立 normal、roughness、metallic 并替换模板对应通道,缺失通道继续沿用所选模板。如果没有辅助图,则完整复用模板 normal/mix。编辑器仍从已发布 Buffer 还原 TileScale 和 ColorRoughnessFactor,不依赖下载包中可能缺失或使用 TNND 包装的 standalone Material。
UV旋转是最终绝对角度,不叠加模板自身可能存在的隐藏旋转,并同时作用于颜色和 packed normal/mix。不要只在图像软件中旋转颜色图,否则颜色方向可能与法线、粗糙度方向错位。
两个公开入口
添加项目纹理
“添加项目纹理”完成一整条导入流程:
- 把选择的图片复制到
res/terrain_custom/textures/。 - 从当前选中地表在合并数组中的层创建项目 Material:使用新的
diffuse,并把模板 normal/mix 与地表参数提取到项目。 - 首次使用时,从 ResourceCache 读取当前内置目录并生成项目完整
config_v1.json。 - 创建或更新
Editor/TextureStyle/project_custom.json。 - 维持现有风格和槽位顺序,自动补齐到固定96层。
- 生成两个合并纹理数组、对应 XML 和九套最终地形 Material。
文件名用于生成项目资源 ID;界面显示名保留所选图片的原文件名。目标文件重名时,编辑器会生成不冲突的新名称,不覆盖已有项目纹理。
生成/更新资源
“生成/更新资源”不增加新纹理,而是根据当前项目的完整 config_v1、TextureStyle 和源 Material 重建:
tiles/Textures/Mix/BaseColor_Terrain.pngtiles/Textures/Mix/BaseColor_Terrain.xmltiles/Textures/Mix/MixColor_Terrain.pngtiles/Textures/Mix/MixColor_Terrain.xmltiles/material/Mix/下九个*_Terrain.material
高级用户或 AI 已经手工调整项目 Material、TextureStyle 或显示名称时,使用这个入口重新生成最终产物。它同样要求目录总数正好为96层。
该按钮只在首次成功添加项目纹理后显示。尚未添加项目纹理时,目录只有82个内置 Material,这是正常状态;此时没有项目资源需要重建,应先使用“添加项目纹理”。MCP 同样只允许对已有项目目录执行 generate,首次导入前会返回 terrain_project_surface_not_configured。
删除选中纹理
在“项目自定义地表”中选中要删除的纹理,点击“删除选中纹理”并阅读确认提示。删除后纹理从选择列表隐藏,原槽位立即可供下次添加复用;其它纹理保持原有顺序。删除不扫描已有地图,也不能通过编辑器撤销。再次导入覆盖该槽位时,旧地图上使用该槽位的地表可能显示为新纹理,甚至无法按原样恢复。操作前请备份项目。
删除时暂不移除原图片、源 Material 或纹理数组层;下次添加项目纹理后,生成器会将新纹理写入已释放的槽位。无需升级客户端二进制。MCP 当前提供添加和重建入口,删除需在编辑器地表面板执行。
手工修改 UV 旋转
导入界面的角度直接成为最终 UV 角度;模板只提供缩放和表面通道。生成的项目源 Material 使用 TileScale 保存最终缩放和旋转:
xml
<!-- value = 缩放X 缩放Y 旋转圈数 0 -->
<parameter name="TileScale" value="0.5 0.5 0.25 0" />第三项是“角度 ÷ 360”,因此 0.25 表示 +90°,-0.25 表示 -90°,0.5 表示 180°。修改项目 res/terrain_custom/materials/*.material 后,点击“生成/更新资源”,编辑器会把新值写入96层最终 Material Buffer。该变换同时旋转 BaseColor 和 normal/mix,不需要修改客户端或 shader。
_mix.png 的四通道格式
项目 Material 虽然把 <资源名>_mix.png 绑定在 normal 槽位,但它不是普通 RGB 法线图,而是地形 shader 使用的四通道线性数据:
| 通道 | 内容 |
|---|---|
| R | 切线空间法线 X |
| G | 切线空间法线 Y |
| B | 粗糙度 Roughness |
| A | 金属度 Metallic |
法线 Z 由 shader 根据 X/Y 重建。该文件按 sRGB=false 解释,并且必须保留 Alpha;非金属地表的 Alpha 通常为0。平坦法线、完全粗糙、非金属的近似默认值是 RGBA=(128,128,255,0)。来自不同工具的法线还可能需要翻转 G 通道。
不能把普通 RGB 法线图直接改名为 _mix.png:普通法线图的 B 通道通常是法线 Z,在这里会被当成粗糙度;缺失或默认255的 Alpha 会被当成完全金属,导致异常反光。普通法线图应使用 _normal、_norm 或 _n 后缀交给编辑器打包。
自动发现与 packed _mix 优先级
选择 stone.png 或 stone_basecolor.png 时,编辑器都以 stone 作为文件族,在同目录按以下顺序处理:
- 显式指定的 packed
_mix; - 自动发现的
stone_mix.png/.tga; - 显式或自动发现的 normal、roughness、metallic;
- 未提供通道沿用所选模板;
- 没有辅助图时完整沿用模板 mix。
text
BaseColor: _basecolor / _albedo / _diffuse
Normal: _normal / _norm / _n
Roughness: _roughness / _rough
Metallic: _metallic / _metal
Packed mix: _mixpacked _mix 会原样采用四个通道,不执行 normal G 翻转,并忽略同时存在的独立通道图。没有 _mix 时,roughness 和 metallic 读取图片 R 通道;普通法线可在界面选择“法线G:保持/翻转”。同一角色出现多个候选文件时会报告歧义,不会按文件时间或扩展名自动选择。_m 不参与自动发现,因为既有资源中该后缀含义不唯一。
通过 MCP 导入或重建
AI 使用 MCP 时必须先查询当前目录,再 Preview,最后 Apply:
text
terrain_list_surface_styles
-> terrain_list_surface_textures
-> terrain_preview_project_surface_import (uv_rotation_degrees: 0 | 90 | 180 | 270,默认90)
-> terrain_apply_project_surface_import
-> terrain_project_surface_wait导入 Preview 接收颜色图片、模板 ID 和 uv_rotation_degrees,默认自动发现同目录辅助图;也可显式传 mix_image_path,或分别传 normal_image_path、roughness_image_path、metallic_image_path,并用 normal_green_mode=keep|flip 控制普通法线。Preview 的 surface_inputs 会列出最终模式、文件来源和 SHA256。Apply 会重新扫描目录并复验全部文件、通道选项、模板和文档状态;新增高优先级 _mix、文件内容变化或选项变化都必须重新 Preview。
对已有项目目录执行纯重建时使用:
text
terrain_preview_project_surface_generate
-> terrain_apply_project_surface_generate
-> terrain_project_surface_wait生成任务是异步操作。terrain_project_surface_status 用于单次查询,terrain_project_surface_wait 用于等待完成。导入和重建只修改项目资源文件,不创建地形 Undo 事务,也不替用户保存当前场景。
写入安全
生成前,编辑器会验证:
- 当前项目和离散瓦片地形已经打开。
Dota2中每个 Style 都存在并具有连续的Items[].Index。- 每个源 Material 都有
diffuse和normal纹理。 - 所有风格合计正好为96个 Material。
- 项目目录可创建和写入。
两个大纹理数组和九套 Material 会先写入项目 editor/terrain 下的临时目录。全部生成成功后,编辑器才备份旧文件并替换正式项目资源;替换失败时会恢复已经移动的旧文件,避免留下新旧产物混合的状态。
生成的项目结构
text
<project>/
├─ editor/terrain/
│ └─ .surface_resource_stage_* # 仅生成期间存在;异常中断时可用于诊断
└─ res/
├─ Editor/TextureStyle/
│ └─ project_custom.json
├─ terrain_custom/
│ ├─ materials/
│ │ └─ <资源名>.material
│ └─ textures/
│ ├─ <资源名>.<扩展名>
│ └─ <资源名>_mix.png
└─ tiles/
├─ tile_config/config_v1.json
├─ Textures/Mix/
│ ├─ BaseColor_Terrain.png
│ ├─ BaseColor_Terrain.xml
│ ├─ MixColor_Terrain.png
│ └─ MixColor_Terrain.xml
└─ material/Mix/
└─ 九个 *_Terrain.materialproject_custom.json 带有 ManagedBy: SCEProjectTerrainTexturesV1。编辑器只自动维护带该标记的项目风格,不会把同名但由用户手工维护的 TextureStyle 当作自己的文件覆盖。
槽位和顺序约束
config_v1.Dota2最多16个风格,每个 Style 最多16个连续槽位。- 项目自动管理的 Style 槽位0是隐藏的悬崖保留槽位。
- 内置目录当前占82层,因此默认给项目 Style 留出14层,其中最多13张为用户可画纹理。
- 未使用的项目槽位会引用有效 Material,并使用
DisableDisplay: true隐藏。 - 不能重排已有风格和槽位。“删除选中纹理”是需要用户确认的破坏性复用例外:删除后槽位可被下次导入覆盖,可能影响已绘制的地图;不会压缩其它槽位。
config_v1 -> Style.Items -> 两个纹理数组 -> Material Buffer的顺序必须完全一致。
“自然风光混合”“花园混合”等内置混合风格来自 texture_group.json。每组前三项是用户可画纹理,第四项是运行时 extend 纹理。Group 的 1-based 顺序会编码进地形扩展权重,不能重排或删除。
客户端兼容性
生成结果仍使用原有逻辑路径、TextureStyle、纹理数组和地形 Material 格式,没有增加客户端 API、顶点编码或 shader 输入格式,因此不提高客户端能力版本。
目标环境必须下载包含 MAX_MIX_MATERIAL=96 的对应平台 shader overlay。缺少 overlay 时,地形会显示为蓝色错误材质。超过16×16、改变混合通道、改变顶点编码或运行时动态扩展数组,仍属于新的客户端能力。
当前边界
- 仅支持离散瓦片地形,不适用于连续高度场。
- “添加项目纹理”可自动发现 packed
_mix或独立 normal、roughness、metallic;缺失通道沿用当前模板。 - 普通法线图不能直接作为
_mix.png使用,必须以 normal 后缀或显式路径交给编辑器打包。 - 不增加自定义瓦片、悬崖、道路或装饰物类型。
- 地表面板可删除当前项目的自定义纹理并复用其槽位,但不会扫描旧地图引用,也不提供 Undo;不支持重排或压缩风格与槽位。
- 直接修改项目 JSON、Material 或图片后不保证热重载;使用“生成/更新资源”并重新打开项目。
验收清单
- 新纹理出现在“项目自定义地表”中,没有
[配置错误]。 - 涂抹结果不是蓝色材质,并显示选择的颜色图。
- 项目中存在独立的
<资源名>_mix.png,表面凹凸和粗糙度与添加前选择的模板纹理一致。 - Undo/Redo、保存和场景重载后结果保持。
- 同一编辑器进程切换有/无项目纹理的项目时,目录数量正确变化,不保留上个项目的自定义项。
- 编辑态与调试运行一致。
- Windows、Android 和 iOS 使用需要支持的旧客户端加载既有项目,确认96层 shader overlay 不改变原有地形。
- 同一批旧客户端加载含项目自定义纹理的场景,确认新纹理正确显示、无蓝色材质且层索引没有错位。
常见问题
按钮提示需要更新编辑器
项目 Material 需要保存到明确的项目路径。旧编辑器只有保存到程序资源目录的内部接口,不能安全生成项目资源;更新编辑器后再使用。
添加后表面细节不符合预期
新颜色图沿用了添加前选中纹理的 normal/mix。切换到更接近目标材质的现有纹理后重新添加,或按高级流程提供自己的 packed normal/mix。
生成时报告不是96层
项目存在手工风格、缺失 Style 或槽位数量不完整。保持已有顺序,补齐隐藏槽位,使全部 Dota2 -> Items 合计为96。
列表显示正确但画成另一张纹理
项目 JSON 被手工修改后没有重建数组,或数组输入顺序与 Style 顺序不同。使用“生成/更新资源”重建,并重新打开项目。
地形显示为蓝色
先检查生成是否完整,再确认当前平台已经下载96层 shader overlay。