Skip to content

离散瓦片地形自定义地表纹理 ​

离散瓦片地形可以使用项目自己的颜色纹理。同一场景不绑定单一风格:内置风格、混合风格和项目自定义风格可以共同涂抹同一张地图。

编辑器通过公开入口生成旧客户端能够读取的项目资源。用户不需要从 Update 目录复制或解密内置 Material、config_v1.json 和 TextureStyle;这些下载资源可能使用 TNND 包装,编辑器会通过 ResourceCache 在内存中读取。

最快工作流 ​

  1. 把颜色图片及可选的 _mix、normal、roughness、metallic 放在同一目录。BaseColor 支持 PNG、JPG、TGA 和 DDS;辅助图支持 PNG、JPG、TGA,packed _mix 必须使用保留四通道的 PNG 或 TGA。
  2. 打开离散瓦片地形场景,在“地表”中先选择一个现有纹理。它会作为新纹理的表面细节模板。
  3. 选择“UV旋转”。默认 90° 用于补偿默认镜头相对地形世界方向旋转了90度;图片已经按地形世界方向制作时选择 0°,方向相反时选择 270°。
  4. 点击“添加项目纹理”,选择自己的颜色图片。
  5. 等待编辑器完成预检、合并和项目文件替换。
  6. 在“地表风格”中选择“项目自定义地表”,再选择新纹理涂抹。
  7. 执行 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.png
  • tiles/Textures/Mix/BaseColor_Terrain.xml
  • tiles/Textures/Mix/MixColor_Terrain.png
  • tiles/Textures/Mix/MixColor_Terrain.xml
  • tiles/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 作为文件族,在同目录按以下顺序处理:

  1. 显式指定的 packed _mix;
  2. 自动发现的 stone_mix.png / .tga;
  3. 显式或自动发现的 normal、roughness、metallic;
  4. 未提供通道沿用所选模板;
  5. 没有辅助图时完整沿用模板 mix。
text
BaseColor:  _basecolor / _albedo / _diffuse
Normal:     _normal / _norm / _n
Roughness:  _roughness / _rough
Metallic:   _metallic / _metal
Packed mix: _mix

packed _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.material

project_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 或图片后不保证热重载;使用“生成/更新资源”并重新打开项目。

验收清单 ​

  1. 新纹理出现在“项目自定义地表”中,没有 [配置错误]。
  2. 涂抹结果不是蓝色材质,并显示选择的颜色图。
  3. 项目中存在独立的 <资源名>_mix.png,表面凹凸和粗糙度与添加前选择的模板纹理一致。
  4. Undo/Redo、保存和场景重载后结果保持。
  5. 同一编辑器进程切换有/无项目纹理的项目时,目录数量正确变化,不保留上个项目的自定义项。
  6. 编辑态与调试运行一致。
  7. Windows、Android 和 iOS 使用需要支持的旧客户端加载既有项目,确认96层 shader overlay 不改变原有地形。
  8. 同一批旧客户端加载含项目自定义纹理的场景,确认新纹理正确显示、无蓝色材质且层索引没有错位。

常见问题 ​

按钮提示需要更新编辑器 ​

项目 Material 需要保存到明确的项目路径。旧编辑器只有保存到程序资源目录的内部接口,不能安全生成项目资源;更新编辑器后再使用。

添加后表面细节不符合预期 ​

新颜色图沿用了添加前选中纹理的 normal/mix。切换到更接近目标材质的现有纹理后重新添加,或按高级流程提供自己的 packed normal/mix。

生成时报告不是96层 ​

项目存在手工风格、缺失 Style 或槽位数量不完整。保持已有顺序,补齐隐藏槽位,使全部 Dota2 -> Items 合计为96。

列表显示正确但画成另一张纹理 ​

项目 JSON 被手工修改后没有重建数组,或数组输入顺序与 Style 顺序不同。使用“生成/更新资源”重建,并重新打开项目。

地形显示为蓝色 ​

先检查生成是否完整,再确认当前平台已经下载96层 shader overlay。