Files
mtgodot-poc/README.md
T
shenandshen c3a6fb973e fix(rendering): checkpoint main-character recovery and visual regression work
Handle late main-character data, guarded model construction, bounded retries and map correction. Validate player model sources and add lifecycle and real-asset visual regressions.

Include pending material and character-selection changes, updated A1 screenshot, and the detailed rendering repair plan. Hair occlusion, full UI parity and final macOS package acceptance remain unfinished.
2026-09-08 08:52:30 +08:00

194 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# mtgodot-poc
「**Godot 4 + 自研资源 loader**」跨平台方案的渲染 Demo。
用一个 C++ GDExtension 把 Metin2 的 `.gr2` 骨骼资源渲染进 Godot,用 Godot 内置渲染器。
> **2026-08-29:并入 `xrender-poc`。** 原先与本仓库并行的 bgfx 自研引擎方案(`xrender-poc`
> 经中期评审([`docs/MIDREVIEW.md`](docs/MIDREVIEW.md)**停止开发**,其可复用部分——
> `libgr2`gr2 v6/v7 读取器,已对拍 Granny)、`formats`.msa/.msm)、`oracle`Granny 真值工具)、
> `tools`libgr2 校验工具)、`docs/reference`(格式逆向笔记)——已 **vendored 进本仓库**。
> bgfx 侧的渲染器 / 平台壳 / 第三方库全部弃用(Godot 取代)。bgfx demo 的参考截图留在
> `test/bgfx-reference/` 供交叉核对。`xrender-poc` 目录本身已删除(2026-08-30)。
自用项目(内部研究,不对外发布),分两阶段推进:
| 阶段 | 平台 | 里程碑 | 产出 |
|---|---|---|---|
| **Phase 1**(当前) | macOS | M0' · M1 · M2 · M2.5 | 中期评审 |
| Phase 2 | Android(一加 13 / Vulkan)· iOSiPhone 16 / Metal | M3 | 三设备各一次 bring-up + 性能留档 |
自用、不对外发布,**无正式 go/no-go 门禁**;三台目标设备都是现代硬件,**全程不涉及 GLES3 / Compatibility 渲染器**,不做中低端 / 老机器。
完整计划见 [`docs/GODOT-POC-PLAN.md`](docs/GODOT-POC-PLAN.md);离可用客户端还差什么见
[`docs/BACKLOG.md`](docs/BACKLOG.md)(分层未完成清单);把参考图那种整张地图画面做出来的实施规格见
[`docs/SHINSOO-WORLD-RENDERING.md`](docs/SHINSOO-WORLD-RENDERING.md)(正式移植,Phase 2 bring-up 之后);
距参考图「目视等价」还差哪些保真化工作见 [`docs/PARITY-GAP.md`](docs/PARITY-GAP.md)。
当前进入游戏、模型/发型、贴地与技能栏问题的分阶段修复步骤,以及结合两个 Godot 项目的
对照验证和 macOS 包验收要求,见 [`docs/RENDERING-REPAIR-PLAN.md`](docs/RENDERING-REPAIR-PLAN.md)
(2026-09-08,实施计划;不表示其中工作已完成)。
---
## 现状
- [x] **M0'** — 脚手架。GDExtension 加载 + `Metin2Model` 注册 + `libgr2` 链接可调用
+ Godot 4.7 工程经 Metal Forward+ 出画。T0.4 实际 `export` 待装 4.7.1 导出模板。
- [x] **M1** — 静态渲染。`gr2``Skeleton3D` + `ArrayMesh` + `Skin` + 材质。
`warrior_cheongrin`75 骨 / 5 表面 / 3324 顶点)正立、朝 +Z、贴图正确
`test/golden/m1-bindpose.png`)。多骨架:`warrior_lord`(v6,74)、`assassin`(v6,95,17 表面)、
`shaman_lord`(**v7**,93) 均正确加载渲染。
- [x] **M2** — 骨骼动画。`Metin2AnimPlayer` `_process``gr2::sample_pose`(跨文件)
**默认 CPU 线性混合蒙皮**(把 libgr2 的 `Σ w·invWorld·world` 直接作用到顶点,每帧重建 mesh)。
`get_bone_global_pose` vs `conv(world)` 全骨 ≤2.6e-5`selfcheck` 0 NaN`dance_1` 等所有动作
头/护甲/躯干正确,与 xrender-poc bgfx demo 一致。
`MTGODOT_GPUSKIN=1` 走**自写蒙皮顶点着色器**`m2_material` `SRC_SKIN`:逐骨完整 4×3 矩阵
存 RGBAF 纹理,绕过 `Skeleton3D` —— Godot 内置 GPU 蒙皮会正交化、丢 Granny 烘在 rig 骨上的
shearwarrior 7 根 / **sura 16 根**,见 `test/shear-bones-survey.md`)。人群场景用它。
**`.msa`**`anim_path``.msa` → motion `.gr2` + `Accumulation` + `MotionEventData`
`get_events()` / `motion_event` 信号,带循环回绕)+ `LoopData` 元数据;播放器 `loop=false`
可播一次并发 `playback_finished`(片段循环次数执行仍在 backlog C4)。
**`.msm`**`gr2_path``.msm` → 自动加载 `BaseModelFileName`(含散包目录扫描)+
`get_hair_options()` 发型目录(发型 mesh 挂接留 Phase 2)。
- [x] **M2.5** — 材质与观感保真。`ShaderMaterial`modulate tex×COLOR×light、
opaque/alpha/alpha-test/add 四模式)+ 方向光阴影 + procedural sky + 引擎雾。
**贴图走 gr2 material 绑定**`build_parts()``tri_groups[].material_index` 把一个 gr2 mesh
拆成多个 Godot surface,各 surface 取 `Mesh::material_textures[matidx]`mesh-local)→
同目录大小写不敏感查 `.dds`;找不到才回退文件名启发式。shaman(1→2 面)/assassin(17→18 面)
各面贴图正确。MODULATE2X 等 stage op 仍只近似(差距清单见 `docs/GODOT-POC-PLAN.md` §M2.5 T2.5.6)。
- [~] **中期评审** — [`docs/MIDREVIEW.md`](docs/MIDREVIEW.md)。结论:桥接层工程量小、
风险基本出清,**建议进入 Phase 2**。`compare.py` 已有进程/截图/结构硬门禁,像素差仍为
advisory;收尾重点是前台/真机性能重测与桥接层全语料 draw 冒烟(默认已是 CPU LBS)。
50 角色压力采样:`test/godot-macos-stress.json`(后台窗口 30fps 节流,仅构建成本
~165ms/角色 和 100 角色破顶到 52ms 是可信信号)。
---
## 环境
| 组件 | 版本 / 位置 | 说明 |
|---|---|---|
| Godot | **4.7.1**`/opt/homebrew/bin/godot`Homebrew cask | 编辑器 + headless |
| godot-cpp | submodule `extension/godot-cpp` @ `101ae38034304346a46ea9ea84ae156d3e860496` | 精确 gitlink 锁定(`.gitmodules` 不跟踪移动分支);bundled `extension_api-4-7.json` |
| Xcode | 26.4.1 | macOS 构建 |
| CMake | 已装;**不需要 SCons** | godot-cpp 走 CMake 路径 |
| libgr2 / formats / oracle / tools | vendored 进本仓库 | 见下「vendored 库」 |
**导出模板**M0' T0.4 / 真正 export 才需要):编辑器内 `Editor → Manage Export Templates → Download`,或 `godot --headless --install-export-templates`。~600MB,版本须与编辑器一致(4.7.1)。
---
## 构建
```bash
git submodule update --init --recursive # 拉 godot-cpp(首次)
./build.sh # Debug;产物 → project/bin/libmtgodot.macos.template_debug.dylib
./build.sh Release # template_release
```
首次会编译 godot-cpp(几分钟)。扩展构建自动带上 vendored `libgr2` + `formats`
只想构建 `libgr2` / `formats` / 校验工具(不碰 godot-cpp):
```bash
cmake -B build-tools -DMTGODOT_BUILD_EXTENSION=OFF -DMTGODOT_BUILD_TOOLS=ON
cmake --build build-tools -j8
./build-tools/tools/gr2fuzz "$PWD/assets" # 全量解析冒烟
./build-tools/tools/gr2dump <file.gr2>
```
## 运行
```bash
# 完整客户端:登录 → 选人 → 进游戏(用仓库内 assets/)
./run-client.command # 或双击
# = MT_ASSETS=$PWD/assets godot --path project res://client_main.tscn
# 打包 .app(需先装 Godot 4.7.1 macOS 导出模板)
./build-macos-client.sh [debug|release] # -> build/export/mtgodot-poc.app
# 编辑器打开
godot -e --path project
# 模型查看器 harness(旧 main_scene
godot --path project res://main.tscn
# headless 冒烟测试(验证 GDExtension 加载 + 类注册)
godot --headless --path project --quit-after 3
# 跑一个真实 gr2 过 libgr2(可选)
MTGODOT_PROBE_GR2="$PWD/assets/PC/ymir work/pc/warrior/warrior_cheongrin.gr2" \
godot --headless --path project --quit-after 3
```
控制台出现 `[mtgodot] Metin2Model registered OK — libgr2 linked; ...` = M0' 的 T0.1/T0.2 通过。
窗口内:拖拽 = 轨道,滚轮 = 缩放,`F2` = 截图(→ `user://`)。
---
## vendored 库(并入自 xrender-poc2026-08-29
| 目录 | 内容 | 谁用 |
|---|---|---|
| `libgr2/` | gr2 v6/v7 只读读取器(header/section/Oodle1/类型树/骨架/网格/曲线/材质)。零第三方依赖。9166 语料 fuzz 0 崩溃;bind pose + 蒙皮对拍 Granny 2.9.12 ≤6.5e-5。含 `dump_materials()`。 | `extension``xrender::libgr2`)、`tools` |
| `formats/` | `.msa`(动作)/ `.msm`(模型 + 发型)/ textscript 解析。 | M2 T2.2/T2.3 起(retarget + motion event |
| `oracle/` | Wine + MinGW 交叉编译的 Granny 真值工具(`oracle.c` + 脚本 + `RUNBOOK.md`)。`oracle.exe` / `granny2_x64.dll` 不入库(体积 + RAD IP),`build-wine.sh` 本地重建。 | M2 数值门禁、M2.5 材质对拍 |
| `tools/` | `gr2dump`(转储)/ `gr2fuzz`(全量解析冒烟)/ `oracle_diff`libgr2 vs oracle 逐字段对拍)/ `anim_probe`(每骨 world 3×3 的 det/shear/scale 探针,查蒙皮走样)。 | libgr2 回归 |
| `docs/reference/` | xrender-poc 的格式逆向笔记(M0M4 施工文档 + PLAN)。见 `docs/reference/README.md`。 | 查格式细节 |
| `test/bgfx-reference/` | bgfx demo 的参考截图 + `noise_floor.json` / `m2-numeric.json` / `assets.list` 基线。 | 与 Godot 输出交叉核对 |
CMake:顶层 `add_subdirectory(libgr2)` + `add_subdirectory(formats)`(跨平台,不碰 godot-cpp);
`extension``target_link_libraries(... xrender::libgr2)``tools`
`-DMTGODOT_BUILD_TOOLS=ON` 开启。
> `libgr2/README.md` 里的 **oodle1.c clean-room 提醒**依然适用:`src/oodle1.c` 是泄露 SDK 端口,
> 仅限内部研究 / 非发布 / 非商用;对外发布前必须 clean-room 重写。
---
## 目录
```
mtgodot-poc/
CMakeLists.txt 顶层:add_subdirectory(libgr2/formats/[tools]/[extension])
build.sh 便捷构建(扩展)
libgr2/ ← vendoredgr2 读取器(xrender::libgr2
formats/ ← vendoredmsa/msm/textscript
oracle/ ← vendoredGranny 真值工具(exe/dll 不入库)
tools/ ← vendoredgr2dump / gr2fuzz / oracle_diff
extension/
CMakeLists.txt mtgodot SHARED + godot-cppconsume xrender::libgr2
godot-cpp/ submodule @ 101ae38034304346a46ea9ea84ae156d3e860496
src/
register_types.{h,cpp} GDExtension 入口
metin2_model.{h,cpp} gr2 → Skeleton3D + ArrayMesh + Skin + 材质
metin2_anim.{h,cpp} 每帧 sample_pose → Skeleton3Dselfcheck
gr2_bridge.{h,cpp} libgr2 POD → Godot 类型;basis + 单位换算
m2_material.{h,cpp} Metin2 风格 ShaderMaterialmix / add
dxt.{h,cpp} DDS DXT1/3/5 软解
assets/ Metin2 资产(.gr2/.dds/locale/OutdoorA1/…,gitignored;换位置设 MT_ASSETS
bgm/ 背景音乐(assets/ 同级,gitignored
project/ Godot 4.7 工程
client_main.tscn/.gd 完整客户端入口(main_scene)→ AppFlow 登录串场
app_flow.gd LOGIN → SELECT → GAME 状态机
main.tscn / main.gd 旧模型查看器 harness
asset_root.gd AssetRoot:资源目录解析(MT_ASSETS / res://../assets / .app 内外)
docs/
GODOT-POC-PLAN.md 开发计划(M0'M4 + 风险 + 验收)
MIDREVIEW.md Phase 1 中期评审
BACKLOG.md 离可用客户端的分层未完成清单
reference/ ← xrender-poc 的格式逆向笔记(archived
test/
golden/ Godot 对拍截图
bgfx-reference/ bgfx demo 参考截图 + 数值基线
*.json noise_floor / m2-numeric / stress
```
## 授权
`libgr2` 全自研,不含 Granny SDK 代码 —— 例外:`libgr2/src/oodle1.c` 是泄露 SDK 的解码路径端口
(见 `libgr2/README.md`,仅限内部研究 / 非发布,对外发布前必须 clean-room 重写)。
本仓库内部研究用途,不对外公开。