289 lines
30 KiB
Markdown
289 lines
30 KiB
Markdown
# 新客户端渲染修复实施路线
|
||
|
||
更新日期:2026-09-08。目标客户端:本仓库 `metin2-client`,第一交付平台为 macOS。
|
||
|
||
本文是实施规格,2026-09-08 已开始第一批 R0/R1 修改;阶段结果见文末执行记录。未标明通过的工作仍待执行,不代表整体渲染或最终包完成。
|
||
|
||
## 1. 目标、依据与当前状态
|
||
|
||
第一交付目标:实际 macOS 客户端进入游戏后显示正确地图和真实人物,身体/发型/装备组合正常,人物在地面上,底部技能栏可用。之后再精细还原 40250 的材质、环境、树木、特效和性能。
|
||
|
||
画面真值优先使用用户当前 40250 Windows 客户端的同资源、同场景截图。EnriqueGF 的场景截图是可行性和场景完整性参考,不能直接当作 40250 像素真值;其主角背对镜头,也不能证明正面发型和所有动画正确。原始骨骼数值以固定版本 Granny oracle 的可复现实测为参照。
|
||
|
||
| 当前问题/证据 | 状态 | 实施要求 |
|
||
| --- | --- | --- |
|
||
| 用户反馈进入游戏出现胶囊、背景异常 | 待真实客户端复验 | 检查地图、实体、相机与加载时序,不直接归因于模型格式 |
|
||
| `game_scene.gd` 已加入 `_sync_main_character()` 和 `_main_model_attempted` | 工作区有补丁,尚未完成最终画面验收 | 检查晚到实体、失败重试、角色切换和重连的生命周期 |
|
||
| 本地 `world_demo.gd` 曾加载真实 A1 地图及模型 | 历史组件证据 | 只能证明这组资源链路可运行,不能证明联机 `.app` 正常 |
|
||
| 发型挡脸、人物悬空 | 用户反馈,根因仍需隔离 | 分别验证变换、蒙皮、深度、地形高度与动画接触点 |
|
||
| 底部技能未显示 | 用户反馈,已有 `quickbar.gd` | 检查创建、布局、图标、服务端槽位恢复,不重新发明快捷栏 |
|
||
| 日志曾出现 `unknown GC header 59 (last: 32,148)` | 历史协议阻塞,是否仍存在待复验 | 若重现,单列协议问题;不得跳过未知包继续解析来伪造联机通过 |
|
||
| 选角 `flip_winding`、材质及视觉测试已有未提交修改 | 实验状态 | 保留现有改动,记录基线,再逐项验证,不全局翻转或覆盖 |
|
||
|
||
历史 README / MIDREVIEW 的阶段完成描述不代表当前最终包通过。现有截图、日志在使用前检查是否存在、属于哪个构建和资源版本。
|
||
|
||
## 2. 两个上游项目的使用边界
|
||
|
||
本路线依据已经检查的固定提交;上游后续变化需要重新审查:
|
||
|
||
- EnriqueGF/metin2-godot:`078d39a41a3ef17c9e09fb9807956cb1a2f16641`。
|
||
- kcanakdag/metin2-godotime:`6a82d793c1d83e34f3e71200fdfc67a78bcb96d3`。
|
||
|
||
| 参考实现 | 本项目的应用方式 | 不应推导的结论 |
|
||
| --- | --- | --- |
|
||
| EnriqueGF:`tools/compare_visual_golden.py` | 引入区域、遮罩、误差阈值和差异图方法 | 截图存在或整体平均误差低不代表脸部正确 |
|
||
| EnriqueGF:`tools/build_character_glb.py`、`godot/client/online/presentation/warrior_actor.gd` | 同一角色离线 GLB 对照;核对身体/发型/武器的组合和动作同步 | 转换包含 TRS 分解、舍弃 shear;不能假定动画无损 |
|
||
| EnriqueGF:`godot/client/online/presentation/avatar_registry.gd` | 借鉴有效实体数据驱动创建、切地图清理、重复数据处理 | 其快照协议不能直接替代我们的原版协议事件 |
|
||
| EnriqueGF:`tools/prepare_legacy_ui_assets.py`、`godot/client/online/ui/` | 核对 `.sub` 裁剪、原版布局和按钮状态 | 西班牙语素材、字体、窗口尺寸不能直接替代当前中文配置 |
|
||
| EnriqueGF:`tools/audit_city_asset_dependencies.py` | 地图资源依赖追踪、缺失分类和报告 | 全部依赖可解析不等于全部已经正确渲染 |
|
||
| godotime:`tools/export_playable.py` | 实际包资源清单、哈希与加载审计,适配 macOS | Web/Linux 通过不代表 macOS 通过 |
|
||
| godotime:`content/profiles/p0-warrior-dog.json`、`client/scripts/content/` | 模型、动作、附件和依赖的统一验证清单 | 三个精选模型通过不代表四职业和全量换装通过 |
|
||
| godotime:`tools/test_browser_accounts.py` | 借鉴双客户端、重连、换装及账户生命周期用例 | 不迁移其 SpacetimeDB 服务端来修复渲染 |
|
||
|
||
参考源码:
|
||
|
||
- [EnriqueGF 固定版本](https://github.com/EnriqueGF/metin2-godot/tree/078d39a41a3ef17c9e09fb9807956cb1a2f16641)
|
||
- [EnriqueGF 场景截图](https://github.com/EnriqueGF/metin2-godot/blob/078d39a41a3ef17c9e09fb9807956cb1a2f16641/docs/images/ingame-shinsoo.png)
|
||
- [godotime 固定版本](https://github.com/kcanakdag/metin2-godotime/tree/6a82d793c1d83e34f3e71200fdfc67a78bcb96d3)
|
||
|
||
直接移植 EnriqueGF 原创代码时保留 MIT 声明和提交来源。godotime 在本次检查的提交没有项目级许可证,先借鉴方法;直接复制实现前明确授权。原始游戏资源的来源与使用范围沿用本仓库 [THIRD-PARTY.md](THIRD-PARTY.md),不把上游许可证视为原版资产授权。
|
||
|
||
## 3. 技术路线与顺序
|
||
|
||
执行顺序:R0 基线 → R1 场景装配 → R2 模型/发型 → R3 材质/环境 → R4 UI → R5 最终包验收 → R6 性能与内容扩展。R4 可在 R1 后独立推进;R5 的资源清单工具可提前建设,最终验收必须等待 R1–R4 完成。
|
||
|
||
1. 保留原版网络协议与当前 GR2 主链路,以最小改动修复实际缺陷。
|
||
2. 引入独立 GLB 对照场景,不先全量转换资源或更换运行时。
|
||
3. 对照决定具体资源采用哪条路径;结果需要记录,不能预设 GR2 或 GLB 必然更好。
|
||
4. 角色与静态物件分别决策。静态物件可先试离线 Godot 资源缓存;人物保留完整仿射矩阵的需求单独评估。
|
||
5. 每项修复必须在真实 GameScene 和导出包中复验。单模型预览只能作为中间证据。
|
||
|
||
## 4. R0:建立可重复基线
|
||
|
||
涉及现有文件:`test/compare.py`、`project/char_select_visual_test.gd`、`project/world_demo.gd`、`project/game_camera.gd`。
|
||
|
||
### 具体步骤
|
||
|
||
1. 记录当前 Git 提交、未提交补丁摘要、Godot/导出模板版本、扩展库哈希、macOS/GPU、渲染后端、窗口和实际渲染分辨率。不能仅凭提交号标识脏工作区构建。
|
||
2. 固定资产来源及哈希:身体、发型、武器、护甲、MSM/MSA、动画 GR2、纹理、地图和环境。两个上游与我们可能使用不同资源版本,必须先核对。
|
||
3. 为每个场景保存地图名、服务器坐标、地图基点、转换后本地坐标、相机位置/目标/FOV、角色朝向、装备、动作及取样时间。
|
||
4. 建立三种独立场景:无网络的单角色实验台;真实资产的 GameScene + FakeClient;实际服务器上的导出 `.app`。
|
||
5. 保存正面、侧面、背面和脚底近景,以及选角界面和游戏全景。待机/跑步/攻击每段至少取开始、中间、结束,过渡动作另测。
|
||
6. 在现有截图工具基础上增加局部区域和差异图。脸、头发、脚底、技能栏不允许被动态遮罩排除;时间文字、随机粒子等可单列遮罩。
|
||
7. 区分两类比较:同引擎修复前后用于自动回归;40250 对照用于保真评估。没有匹配的相机和动作时,只能做人工结构检查,不执行严格像素判定。
|
||
|
||
拟新增产物(尚未实现):`test/rendering/cases.json`、`test/rendering/README.md`、`tools/rendering/compare_regions.py`。本地日志/截图/报告建议放 `build/rendering/<run-id>/`,不覆盖失败证据。
|
||
|
||
阈值:先在不改代码的条件下重复采样三次,测量阴影/抗锯齿噪声,再设置每区域阈值。报告包含 MAE、RMSE、变化像素比例和遮罩范围;不能为了让错误图片通过而放宽阈值。
|
||
|
||
完成条件:每条用例可由配置重复启动,并能将截图关联到确定的代码、资源、相机和构建;缺参考图的用例标为待验证。
|
||
|
||
## 5. R1:修复主角装配、地图定位与相机
|
||
|
||
涉及现有文件:`project/game_scene.gd`、`project/net_world.gd`、`project/net/mapcoord.gd`、`project/ui/player_view.gd`、`project/game_camera.gd`。必要时追踪 `extension/src/net/m2_client.cpp` 的事件顺序及 `extension/src/metin2_world.cpp` 的地图数据。
|
||
|
||
### 具体步骤
|
||
|
||
1. 增加定点诊断:阶段进入、地图就绪、主角 VID 获得、实体行有效、模型创建、贴地定位、相机开始跟随。每条带角色/场景生命周期编号,避免把上一次登录数据误认为当前数据。
|
||
2. 复核现有 `_sync_main_character()`:明确“等待数据、加载中、成功、失败”的状态;缺 race 等必要数据时保持等待,重复事件不创建重复人物。
|
||
3. 检查 `_main_model_attempted` 是否在失败后永久阻止恢复。数据或资源就绪条件变化时允许受控重试;永久资源错误显示明确失败原因,不能每帧重复加载或刷日志。
|
||
4. 切角色、地图切换、重连时清理旧模型/相机目标/信号并重置对应状态。异步完成结果必须核对是否仍属于当前角色与场景。
|
||
5. 统一通过 MapCoord 转换:服务器全局厘米 → 地图本地米。现有地图本地 Z 约定与上游不同,禁止直接复制对方轴翻转或地图中心公式。
|
||
6. 验证坐标往返、合法边界及高度查询位置。`(0,0)` 可是合法地图基点,地图是否就绪应有明确状态,不能仅靠非零基点推断。
|
||
7. 在地图可查询、角色位置有效后计算地面高度并绑定相机;模型就绪后移除胶囊。资源等待期间提供加载状态,不能把永久占位当正常游戏画面。
|
||
|
||
### 必须补充的回归
|
||
|
||
- 主角 VID 在 setup 前已有、setup 后出现、实体行再晚一帧、多帧后出现。
|
||
- 不发 `entity_main_set`,只更新实体存储,最终仍创建主角。
|
||
- 重复主角事件只产生一个模型;缺 race 时不使用错误职业创建人物。
|
||
- 加载失败有可见原因;条件恢复后可受控重试;旧加载不会覆盖新角色。
|
||
- A1/C1 各一个合法出生点;基点为零的合成坐标用例;地图外坐标被明确诊断。
|
||
- 切角色、重连、切地图后相机跟随当前人物,旧节点与旧状态不残留。
|
||
|
||
测试落点:扩展 `project/gamescene_test.gd`、`project/app_flow_lifecycle_test.gd`;新增真实资源的 GameScene 视觉用例。FakeClient 的字段/信号需匹配实际接口。
|
||
|
||
完成条件:自动回归通过;真实 GameScene 截图同时出现正确地表与真实主角。协议若中断,保留本地通过结果,但将实际联机验收标为未通过。
|
||
|
||
## 6. R2:修复身体、发型、武器与贴地
|
||
|
||
涉及现有文件:`extension/src/metin2_model.cpp`、`extension/src/metin2_anim.cpp`、`extension/src/gr2_bridge.cpp`、`project/ui/player_view.gd`、`project/ui/equip_model.gd`、`project/ui/race_spec.gd`、`project/ui/char_select_screen.gd`。
|
||
|
||
### 同资源对照与定位顺序
|
||
|
||
1. 先选用户出错角色的确切身体/发型/装备;再建立男战士最小对照。GLB 转换必须使用同一组源文件,记录转换器版本与参数。生成文件留在隔离输出目录。
|
||
2. 在统一实验台逐步加载:身体静态绑定姿势 → 身体动画 → 加发型 → 加武器 → 换护甲。每一步保存矩阵、包围盒、贴图绑定和截图。
|
||
3. 检查模型初始 placement、单位缩放、轴转换、父子节点变换是否重复应用。分别核查三角形绕序和负缩放,不能以全局 `flip_winding` 代替定位。
|
||
4. 对身体和发型按骨名核对 mesh binding、骨架索引、inverse bind、当前 world/skin 矩阵。验证发型是否错误重复乘身体变换,是否使用了另一套不兼容的绑定姿势。
|
||
5. 检查附件共享的动画时间与过渡状态。身体切动作/换装时,发型不能停留在旧姿势。武器验证手部附件空间,避免在 model-local 与 world-space 之间重复转换。
|
||
6. 先用不受光照影响的诊断材质、线框或深度视图判断几何是否错误;几何正确而发型仍盖脸时进入 R3 检查深度和混合。
|
||
7. 数值正确后比较 GR2 CPU、GR2 GPU 与 GLB 的同时间画面。对关键骨骼矩阵、选定顶点和完整动画周期采样,保留已有 oracle 精度要求,不只检查 NaN。
|
||
|
||
### 贴地专项
|
||
|
||
1. 分开记录实体基准高度、地形采样高度、模型局部原点和脚部接触点。
|
||
2. 平地待机时用足底接触点判断高度;行走/攻击存在抬脚,不能用动画每帧 AABB 最低点强行贴地,否则人物会抖动。
|
||
3. 测试坡地、台阶或可行走建筑表面,以及地图边界。确认所采样的是人物实际站立表面。
|
||
4. 阴影检查与几何检查分开:阴影偏差可造成悬空观感,但不能用加深阴影掩盖高度错误。
|
||
5. 建议初始平地接触误差上限为 2 cm;这是待以资源与 40250 校准的项目目标,不是原版已证实精度。腾空动作不使用该判据。
|
||
|
||
### 路线决策
|
||
|
||
| 实测结果 | 后续动作 |
|
||
| --- | --- |
|
||
| GR2 数值正确,仅材质/装配错误 | 修复现有渲染与组合,不迁移动画 |
|
||
| GLB 在选定资源上可靠,GR2 缺陷短期难解决 | 为该资源提供可回退的 GLB 适配,保持相同的角色表现接口 |
|
||
| GLB 丢 shear 或过渡不一致 | 不将该角色纳入迁移范围;保留失败样本 |
|
||
| 静态 GLB/原生资源缓存画面一致且加载更快 | 单独推进静态物件缓存,与角色动画路线解耦 |
|
||
|
||
GLB 扩大范围前必须覆盖四职业、实际使用的性别/护甲/发型变体,以及待机、走、跑、攻击、受击、死亡和选角动作。缺少资产时明确未覆盖,不以一个战士替代全体结论。
|
||
|
||
完成条件:出错角色的正面/侧面/背面及关键动作通过;换装、重新选角后仍正确;记录 GR2/GLB 选择依据。清理临时强制绕序、调试打印和 `/tmp` 截图导出时只删除本轮明确归属的诊断代码。
|
||
|
||
## 7. R3:材质、地形与环境校准
|
||
|
||
涉及现有文件:`extension/src/m2_material.cpp`、`extension/src/static_object.cpp`、`extension/src/terrain_splat.cpp`、`extension/src/environment_builder.cpp`、`extension/src/metin2_world.cpp`、`project/ui/char_shadow.gd`。
|
||
|
||
### 具体步骤
|
||
|
||
1. 逐 surface 输出源 mesh、tri-group、材质槽、最终纹理和渲染状态。确认 mesh-local 材质索引没有误当成全局索引,贴图回退有明确诊断。
|
||
2. 身体、脸等不透明面验证深度写入;发丝按资产语义选择 alpha-test;真正半透明面单独混合。不要把所有头发强制成同一模式,也不要对所有表面关闭背面剔除。
|
||
3. 同贴图下比较标准材质和自定义 shader,逐项打开光照、顶点色、透明、雾。检查 DDS 解码、颜色空间、alpha、mipmap 和双重 gamma。
|
||
4. 身体、头发、武器分开检查投影与受影。正面、侧面、逆光及脸部重叠处验证深度;根据场景尺寸校准 shadow bias。
|
||
5. 地形逐层验证 tile/alpha splat 对应、UV 比例、接缝和法线。固定至少一处道路/草地边界作为回归,防止纹理层顺序交换。
|
||
6. 列出地图物件:应有、找到资源、解析成功、实例化、可见、失败原因。资源 CRC 可解析不等于模型已画出,树木占位必须单独计数。
|
||
7. 基于原 `.msenv` 对照太阳方向、角色/背景光、环境光、雾距离与天空;逐项记录 Godot 近似规则。EnriqueGF 的固定 filmic/雾参数只作实验参照。
|
||
8. 完成角色与场景单项校准后再组合全景,避免同时改曝光、贴图与相机导致无法归因。
|
||
|
||
完成条件:脸/身体不误透明,发丝边缘和遮挡正确;道路与草地层正确;主要建筑不缺材质;角色高度与阴影分别通过;每项与 40250 的剩余差异有说明。
|
||
|
||
## 8. R4:选角界面与技能栏
|
||
|
||
涉及现有文件:`project/ui/char_select_screen.gd`、`project/ui/ui_assets.gd`、`project/ui/quickbar.gd`、`project/game_scene.gd`。
|
||
|
||
### 具体步骤
|
||
|
||
1. 对照当前中文 40250 的 `uiscript`、`.sub`、字体及图集,记录选角背景、角色相机、按钮、任务栏、快捷槽的来源与尺寸。
|
||
2. 检查 `.sub` 裁剪边界、大小写路径、透明通道与纹理加载失败;输出 UI 依赖清单。
|
||
3. 从 GameScene 开始检查快捷栏是否创建、挂在正确 CanvasLayer、可见、位于窗口内;核对缩放、锚点、裁剪和其他窗口遮挡。
|
||
4. 跟踪 `quickslots_changed` 与 `restore_from_server` 的调用时序:初始槽位、晚到数据、重新登录均应恢复。保留现有服务端 36 槽与本地 4 页 × 8 格映射。
|
||
5. 将空槽、未学习技能、图标缺失、技能不可用、冷却中区分呈现。不得通过凭空填充技能图标让截图看似正常。
|
||
6. 使用确实已学习并已配置的技能验证图标、拖放、翻页、数字键/F 键和冷却;UI 对比先用 FakeClient,真实施放在适用测试环境下执行。
|
||
7. 验证背包/聊天打开关闭后输入焦点,避免空格攻击误触 UI 按钮。
|
||
8. 按 1280×720、1920×1080 和实际 Retina 窗口验证逻辑尺寸/物理像素关系;中文字体宽度单独检查。
|
||
|
||
完成条件:选角画面达到已记录的参考布局;底部栏始终可见,槽位状态真实;切角色/重连能恢复;技能冷却和输入行为保持正确。
|
||
|
||
## 9. R5:最终 macOS 包与验收证据
|
||
|
||
涉及现有文件:`build-macos-client.sh`、`script/live_smoke_test.sh`、`project/live_smoke_test.gd`、`project/asset_pack.gd`、`project/bake_asset_index.gd`。
|
||
|
||
### 具体步骤
|
||
|
||
1. 扩展构建清单,记录代码版本及脏补丁摘要、构建参数、扩展/模板版本、资源及实际产物哈希。
|
||
2. 对实际 `.app` 检查身体、发型、装备、动作、地图、UI 图标依赖是否存在且可加载。清单生成后仍要启动包验证,不能用工作区资源替代包内检查。
|
||
3. 从不依赖开发者资源路径的目录启动最终包;验证资源解析不会偷偷回退到源码 checkout。用受控资源根测试覆盖此情况。
|
||
4. 执行只读登录冒烟,再运行有画面和输入的 GameScene 验收。现有脚本不是完整视觉测试;需新增或扩展包内测试场景并保存截图。
|
||
5. 移动、攻击、换装等会改变服务端状态的用例使用适用测试角色/服务器;不要把现有冒烟默认包含的聊天发送当作渲染验收必需动作。
|
||
6. 两客户端用例验证角色互见、移动朝向、武器/护甲变化、断开移除及重连重建;同时检查本地与远端外观。
|
||
7. 排除凭据、私有日志、源码资产归档和临时探针出现在普通交付包中。若通过带探针的包定位问题,移除探针后还要对最终普通包重新冒烟。
|
||
8. 将通过记录绑定到交付 `.app` 的确切构建。此后任何影响画面的代码、资源、导出设置变化,都使相关验收失效,需要重测受影响范围。
|
||
|
||
### 现有命令与覆盖边界
|
||
|
||
以下命令在仓库根目录运行。执行前检查本机 Godot、扩展和资源配置;这些是已存在的入口,本文没有执行它们或宣称通过。
|
||
|
||
```bash
|
||
godot --headless --path project --script gamescene_test.gd
|
||
godot --headless --path project --script equip_model_test.gd
|
||
godot --headless --path project --script environment_test.gd
|
||
godot --path project --script char_select_visual_test.gd
|
||
./build-macos-client.sh release
|
||
./script/live_smoke_test.sh --no-build --no-mutations --no-reconnect
|
||
```
|
||
|
||
- Headless 测试仅证明其断言覆盖的逻辑,不能证明实际 GPU 画面正确。
|
||
- 当前选角视觉脚本有实验性诊断,使用前复核其输出和退出行为;它不是完整 40250 比较器。
|
||
- `--no-mutations` 不覆盖移动、聊天、重连、换装和攻击;此处同时给出 `--no-reconnect` 以明确首轮只读范围。
|
||
- 当前脚本包含特定服务器地址与端口,运行前检查是否仍是目标环境;凭据只通过既有本地配置/环境提供,不写进报告。
|
||
- 现有产物路径为 `build/export/mtgodot-poc.app`;日志在 `build/live-smoke/`。保留每次结果时复制到独立 run-id 归档,避免脚本固定路径覆盖历史。
|
||
|
||
### 第一版交付检查表
|
||
|
||
- [ ] 首次进入、切角色、重连后出现真实主角,地图和相机正确。
|
||
- [ ] 用户出错角色的身体/发型/装备在正面及动画中正常。
|
||
- [ ] 平地和选定坡地测试通过,脚底与阴影分别正确。
|
||
- [ ] 底部任务栏可见,已配置技能的图标、输入、恢复、冷却正确。
|
||
- [ ] 材质与地图关键区域通过固定场景比较,差异图有人审阅。
|
||
- [ ] 最终普通 `.app` 独立启动,关键资源无开发目录回退。
|
||
- [ ] 协议错误未导致用例提前终止;未完成的联机项明确标注。
|
||
- [ ] 日志、截图、报告和包哈希对应同一次构建。
|
||
|
||
上述为本次内部 macOS 修复版交付标准,不代表全游戏、所有地图或所有平台均已验收。
|
||
|
||
## 10. R6:性能、缓存与内容扩展
|
||
|
||
在 R1–R5 通过后执行,不以优化替代正确性修复。
|
||
|
||
1. 固定场景采集 1/8/20/50 个角色的 CPU/GPU 帧时间、p95/p99、内存、冷加载与重复加载耗时,明确前台/后台和帧率限制。
|
||
2. 量化当前 CPU 蒙皮逐帧构建网格的成本;GPU 路径先通过数值与画面回归,再扩大启用范围。
|
||
3. 选择一组代表性静态建筑试缓存,缓存键至少包括源资源、转换器版本、坐标和材质选项;改变任一输入必须失效重建。
|
||
4. 测量缓存对冷加载、包体和内存的影响,存在收益再扩大导入规模。保留原始资源来源和可重建流程。
|
||
5. 树木、效果、LOD 和其他地图分别建立缺失清单与回归场景。占位替代物不能计入原版模型已完成数量。
|
||
6. 最后扩展 Android/iOS 独立验证;macOS 的画面和性能结果不能直接外推。
|
||
|
||
## 11. 任务拆分与执行记录
|
||
|
||
每项宜形成一个可独立复查的补丁;无需先完成所有工具才修复已定位的问题。已有用户改动应在相邻上下文中保留,不因路线实施而重置。
|
||
|
||
| 任务 ID | 交付物 | 前置条件 | 当前状态 |
|
||
| --- | --- | --- | --- |
|
||
| R0-01 | 固定资源/场景基线与区域截图配置 | 可用参考资源 | 已有 A1/C1 实景入口和部分哈希;区域差异待补 |
|
||
| R1-01 | 主角晚到、重复事件、重连回归与修复 | R0 最小基线 | 晚到/重入/重试回归通过;真实重连待验 |
|
||
| R1-02 | 地图坐标、高度、相机就绪检查 | R1-01 | A1/C1 晚到定位实景通过;坡地/边界待验 |
|
||
| R2-01 | 同战士 GR2/GLB 实验台及对照报告 | R0 | 待执行 |
|
||
| R2-02 | 发型/身体/附件修复及路线决定 | R2-01 | CPU 绕序、GPU 动态取景和选角朝向已修复;8 个种族 GPU 待机基体矩阵已通过,装备/动作/最终包待验 |
|
||
| R3-01 | 深度/材质/环境与地形校准 | R1、R2 几何稳定 | 材质已有改动,待验证 |
|
||
| R4-01 | 选角、技能栏装配与数据恢复 | R1 | 快捷栏重叠修复及服务器恢复回归通过;真实登录数据待验 |
|
||
| R5-01 | 包资源清单、最终 `.app` 冒烟与画面报告 | R1–R4 | 待执行 |
|
||
| R6-01 | 性能基线与静态资源缓存试验 | R5 | 后续 |
|
||
|
||
每项完成记录必须包含:问题复现、确认根因、修改文件、源资源哈希、实际执行命令、断言/截图结果、包或库哈希、未覆盖范围。失败时记录下一步所需证据;不要把“方案合理”“截图已生成”更新成通过。
|
||
|
||
与现有文档的关系:本路线聚焦用户当前渲染故障和首个 macOS 修复包;[SHINSOO-WORLD-RENDERING.md](SHINSOO-WORLD-RENDERING.md) 提供世界渲染背景,[PARITY-GAP.md](PARITY-GAP.md) 和 [BACKLOG.md](BACKLOG.md) 保留更广范围。后续只在实测完成时同步这些文档的对应状态。
|
||
|
||
### 2026-09-08 第一批实施记录
|
||
|
||
- 修改 `game_scene.gd`:setup 完成相关接线后才开始兜底;加载期间阻止网络事件重入;按 VID/race/资源根区分模型;失败间隔 1 秒最多尝试 3 次;丢弃构建期间失效的主角结果;避免重复动画订阅和每帧重置人物位置。
|
||
- 发现地图路径原来只在 setup 时按已收到的主角位置选择。新增首次有效主角位置到达后的地图重选,复用已有地图重载和相机/移动同步基点定位函数。
|
||
- 修改 `ui/player_view.gd`:拒绝非法 race、缺失身体文件及解析失败的源文件。模型节点在入树时才实际加载,因此使用源文件预检,不能把入树前为空的 `get_info()` 当成加载失败。
|
||
- 新增 `main_character_sync_test.gd`:测试失败重试、晚到/无信号实体、重入、重复事件、移动不回滚、过期构建等,已执行得到 `failures=0`。注入失败用例的 warning 属预期。
|
||
|
||
### 2026-09-08 R2/R4 后续记录
|
||
|
||
以下为历史定位过程,早期 C++ 实验加载了旧 debug 扩展,相关排除结论无效;以文末复核记录为准。
|
||
|
||
- 确认用户选角用的 `HairIndex 0` 由 `warrior.msm` 精确映射到
|
||
`hair/hair_1_1.gr2` 与 `warrior_hair_01.dds`;新增解析回归,避免把默认路径或颜色猜测为实际配置。
|
||
- 选角实景中,`warrior_5_1.GR2`(63 骨)与 `hair_1_1.gr2`(74 骨)组合仍无脸部可见。去除发型后脸部完整,故护甲/脸部几何未丢失;分别使用当前身体蒙皮、强制发型绑定姿势、源发型 alpha 和背面剔除渲染均无差异。没有提交这些无效的猜测性改动。下一步校验角色选择协议的 `hair_part` 语义与标准发型编号,而不是继续调整绕序、动画矩阵或透明参数。
|
||
- 修复 `root/msm` 覆盖规格缺少 `PathName` 时的解析回退:原逻辑只查职业根目录,漏掉 `hair/` 子目录,导致 `HairIndex 1001..1012` 找不到模型并静默保留 `PlayerView` 默认的 `hair_1_1`。`race_spec_test.gd` 现覆盖真实 1001 解析和文件定位;选角视觉用例确认 1001 实际替换为 `hair_2_1.gr2`。发型前脸遮挡尚未随该修复消失,继续作为几何组合项跟踪。
|
||
- 移除 `Hud` 中覆盖真实栏位的静态空快捷栏;`Quickbar` 现在有明确的底部锚点尺寸和更高绘制层级。`skill_test.gd` 验证服务端 `type=2` 技能槽恢复后图标可见,且 `race_spec_test.gd`、`skill_test.gd` 已通过。
|
||
- `gamescene_test.gd` 与 `equip_model_test.gd` 已通过;前者故意使用缺失地图,其预期加载错误不能当成真实地图测试通过。
|
||
- 新增 `gamescene_visual_test.gd`:Apple M4 / Metal Forward+ / Godot 4.7.1 上已执行 A1/C1;A1 加载 20 区块/601 物件,C1 加载 20 区块/565 物件,身体加发型共 4 个表面,实体定位断言通过。两者均使用 FakeClient,未连接实际服务器。
|
||
- 截图人工观察:地图和真实人物出现;UI 仍有布局/风格问题,不能标为 R3/R4 完成。选角截图仍复现发型遮脸;单独翻转 winding 的试验未解决,未保留新的绕序修改。
|
||
- 用例命令、输出位置和验证边界见 [test/rendering/README.md](../test/rendering/README.md)。早期失败截图保留在 `build/rendering/`;后续脚本变化应重新执行,不复用旧报告作为新代码证据。
|
||
- 尚未完成:GLB 对照、发型根因修复、完整视觉基线与区域阈值、真实服务器重连、最终 macOS 包验收、R6 优化。下一优先项是发型的身体/附件变换与深度隔离。
|
||
|
||
### 2026-09-08 R2 根因复核与修复
|
||
|
||
- 构建复核:`build` 为 Release,编译更新 release dylib,但本地 Godot 加载仍停留在 9 月 7 日的 debug dylib。此前 inverse-bind、alpha 和剔除实验没有加载修改后的扩展,不能用它们排除根因。新增 `bash script/rendering_test.sh`,构建后同步本地加载库、重签名、输出哈希并运行绕序回归。
|
||
- 冻结动画后改用双面材质显示完整后背,证实原选角相机在人物背后;身体背面被剔除,露出远侧正面内壁,后脑头发遂表现为“盖脸”。`cpu_skin()` 重建身体和发型索引时忽略 `flip_winding`,已对齐静态/GPU 网格的索引顺序;`PlayerView` 设置 PC 绕序,选角 pivot 从 -90° 改为 +90°。
|
||
- 真实 Metal 选角复核:`main_part=20009`、`hair_part=0` 的脸、肩甲、护腕及裙甲完整,头发位于头顶;保留头发和原透明贴图。颜色/护甲与用户参考资源的进一步一致性仍待校准,不标为 40250 像素验收。
|
||
- 更正 PathName 结论:MSM 中原有 PathName;`RaceSpec` 的空 SpecialPath 错误覆盖父级路径。已修复继承,并去除引号 token 的词法标记。前轮 hair 子目录回退仅缓解此问题。
|
||
- `character_winding_test.gd` 对比绑定姿势及待机 0/0.5/1 秒的逐三角形反向索引,覆盖身体与发型,结果 `failures=0`。`race_spec_test`、`equip_model_test`、主角恢复回归通过;A1 GameScene 重新加载 20 区块/601 物件,主角定位及真实模型断言通过。
|
||
- 选角输出现在按独立目录保存 `selection.png`、`report.json` 和发型纹理,报告包含实际 debug dylib、身体/头发/贴图哈希、引擎和取样时间。默认发型 CPU 截图:`build/rendering/selection-1788843070-9087/selection.png`;1001 GPU 用例:`build/rendering/selection-1788843071-9069/selection.png`。
|
||
- 未覆盖:全职业、完整动作/换装矩阵、GLB 同资源对照、坡地足底误差、40250 同相机比较、真实联机和最终 macOS 包;R2 整体仍未关闭。
|
||
- GPU 1001 取景根因修复:GPU 顶点着色器变形不会改变 `MeshInstance3D.get_aabb()`,选角此前仍以绑定姿势盒取景,故角色被推到窗口上方。`Metin2Model` 现首帧采样实际蒙皮包围盒用于剔除,并按需提供当前姿势包围盒;`CharSelectScreen` 收到 GPU 就绪通知后用该盒重新取景。`char_select_visual_test.gd` 在冻结 0.5 秒参考姿势后也走同一生产取景路径,并在报告中保留相机与网格包围盒数据。Apple M4 / Metal 的 HairIndex 1001 GPU 截图 [selection-1788844385-11872](../build/rendering/selection-1788844385-11872/selection.png) 人工审阅通过,脸部、发型、盔甲与完整人物均在画面内;对应 debug dylib SHA-256 为 `a268eef3f5cd1fc263652c4e0a9c3693f33f359b3706aa6850525c8e52108b39`。
|
||
- GPU 路径仍保持环境变量启用的实验状态;1001 发型和带装备场景当前只覆盖男战士。完整职业的装备、动作、地图与性能测试仍按 R2/R6 的未完成项推进。
|
||
- 追加 GPU 基体矩阵:使用 `--job=0..7 --main-part=0` 在同一 Apple M4 / Metal 环境生成八种种族的选择截图;全部装配断言通过,人工审阅的 [八种族联系图](../build/rendering/r2-matrix-gpu-contact-sheet.png) 中人物、脸部和默认发型均完整入框。此覆盖仅是无装备的待机选择画面,不替代每职业装备、动作或 40250 参考对比。
|