fix(models): MMD 材质对齐——补回双面标志、规范化 PBR 参数、可选 unlit 着色

背景(用户反馈 + 本地用真 Assimp 6.0.4 复现):
PMX 的着色模型(卡通阶梯 + 球面贴图 + 平坦环境光)与 glTF PBR 不是一回事,
Assimp 转换会丢掉其中一部分。实测样本【奥黛塔】_by_原神.zip(39 个材质):

1. 主因:PMX 里 36 个材质带 drawFlag bit0(不剔除背面),而导出的 GLB 里
   doubleSided 一个都没有 -> 头发/裙摆/睫毛这类薄片被单面剔除,
   看起来就是颜色/贴图不对;
2. PMX 的 shininess/specular/ambient 与 PBR 无映射;Assimp 还会带上
   KHR_materials_specular / KHR_materials_volume 等与 MMD 无关的扩展;
3. Assimp 把 accessor.min/max 写坏(实测 min = 2.2250738585072014e-308),
   Godot 等客户端用它算包围盒。

修复:
1. 新增 src/models/pmx-materials.ts:只读 PMX 材质段(布局与权威库 mmd-parser
   一致,注意贴图索引宽度是 1 字节),拿到 name/diffuse/specular/shininess/
   ambient/drawFlag/球面贴图/toon/faceCount;
2. 新增 src/models/glb-materials.ts:转换后按索引把 PMX 参数补回 GLB ——
   doubleSided、metallicFactor=0、roughnessFactor=clamp(1-shininess/100,0.5,1)、
   baseColorFactor x diffuse(含 alpha);清掉与 MMD 无关的扩展;
   修正全部浮点 accessor 的 min/max;支持 KHR_materials_unlit(MODEL_SHADING);
3. 抽出 src/common/glb-chunks.ts(JSON/BIN chunk 读写),vrm-writer 改为复用;
4. 能力边界写清楚:PMX 的球面贴图(该模型 15 项)与 toon 阶梯在 glTF core 里
   没有对应槽位,任何转换器都无法保留,数量写进 conversion_note 供审核查看;
5. 新增 test/mmd-materials.spec.ts 9 项;规模 15 文件 / 220 项;
6. 新增 MODEL_SHADING 配置(默认 pbr,可选 unlit),文档同步(README.md/.txt、DSH.md、.env.example)。
This commit is contained in:
opendance
2026-09-16 18:55:25 +08:00
parent ae8a68e98f
commit eebccd55b4
18 changed files with 982 additions and 86 deletions
+39 -8
View File
@@ -1,5 +1,5 @@
================================================================
OpenDance Studio -- Web 管理服务端 v0.2.4 使用说明
OpenDance Studio -- Web 管理服务端 v0.2.5 使用说明
================================================================
本服务端是 OpenDance Studio 三端中的第一端, 负责管理歌曲、VRM 模型与
@@ -8,6 +8,27 @@ OpenDance Studio -- Web 管理服务端 v0.2.4 使用说明
重要: 本服务端 不部署、不管理 MySQL。数据库为部署方提供的现有实例,
连接信息通过 .env 注入。
v0.2.5 修订 - MMD 材质/着色对齐
PMX 的着色模型(卡通阶梯 + 球面贴图 + 平坦环境光)与 glTF PBR 不是一回事,
Assimp 转换会丢东西。实测样本 【奥黛塔】_by_原神.zip(39 个材质):
1. 修复"看起来颜色/贴图不对"的主因: PMX 里 36 个材质带"不剔除背面"标志,
而 Assimp 导出的 GLB 里 doubleSided 一个都没有 -> 头发/裙摆/睫毛这类
薄片被单面剔除。现在新增 pmx-materials.ts(只读 PMX 材质段), 转换后按
drawFlag 补回 doubleSided。
2. PBR 参数规范化(glb-materials.ts): metallicFactor=0、
roughnessFactor=clamp(1-shininess/100, 0.5, 1)、baseColorFactor 乘上 PMX
diffuse(含 alpha); 清掉 Assimp 带出的、与 MMD 无关的 KHR_materials_specular
/ volume / transmission / ior / emissive_strength; 顺手修正 Assimp 写坏的
accessor.min/max(实测 min 被写成 2.2e-308, Godot 用它算包围盒)。
3. 新增 MODEL_SHADING(默认 pbr, 可选 unlit): unlit 给每个材质写
KHR_materials_unlit, 颜色 = 贴图 x baseColorFactor、与场景光照无关,
最接近 MMD 的平涂观感(three.js 与 Godot 都支持)。
4. 能力边界: PMX 的球面贴图(该模型 15 项)与 toon 阶梯在 glTF core 里没有
对应槽位, 任何转换器都无法原样保留; 数量会写进 conversion_note。
5. 新增 9 项测试(test/mmd-materials.spec.ts); 规模 15 文件 / 220 项。
6. 注意: 材质修正在转换时生效, 已有模型需重新导入(reanalyze-models.mjs
只刷新分析与缩略图, 不会重转材质)。
v0.2.4 修订
1. 修复缩略图"白模": 缩略图渲染器原先刻意不解码贴图, 只用 baseColorFactor
上色; 而 MMD(PMX 转换)模型的 baseColorFactor 基本都是白色, 于是列表页与
@@ -69,11 +90,11 @@ v0.2.1 修订
2. 准备一个现有的 MySQL / MariaDB 实例, 并建好库与账号(见下方"前置要求")
本项目不会创建数据库本身
3. 取得发布包并校验(地址用你们自己的制品库替换)
curl -LO https://<制品库地址>/opendance-web-v0.2.4.tar.gz
curl -LO https://<制品库地址>/opendance-web-v0.2.5.tar.gz
curl -LO https://<制品库地址>/SHA256SUMS
sha256sum -c SHA256SUMS # 期望输出 "OK"
4. 解压并生成配置(交互式引导, 逐项问答, 口令不回显)
tar -xzf opendance-web-v0.2.4.tar.gz && cd opendance-web-v0.2.4
tar -xzf opendance-web-v0.2.5.tar.gz && cd opendance-web-v0.2.5
bash deploy/init-env.sh
5. 安装(建用户与目录 -> 装依赖 -> 迁移 -> 注册系统服务 -> 等健康检查)
bash deploy/install.sh
@@ -131,8 +152,8 @@ v0.2.1 修订
(本项目不会创建数据库本身, 也不需要 GRANT OPTION / FILE / SUPER 等管理权限)
部署步骤
tar -xzf opendance-web-v0.2.4.tar.gz
cd opendance-web-v0.2.4
tar -xzf opendance-web-v0.2.5.tar.gz
cd opendance-web-v0.2.5
bash deploy/init-env.sh # 首次启动引导: 逐项问答生成 deploy/.env(见下)
bash deploy/install.sh # 已以 root 登录, 不需要 sudo
@@ -263,7 +284,12 @@ deploy/.env 初始化引导(deploy/init-env.sh)
(RHEL 系 dnf install -y assimp; install.sh 现在会尝试自动安装)。
装好后不需要重启服务; 若不在服务 PATH 中, 在 deploy/.env 里把 ASSIMP_BIN
设为绝对路径。只上传 .glb / .vrm 则不需要它。
- 列表/审核里的缩略图是"白模"(纯白模型)
- 导入后的模型颜色/观感与 MMD 里不一致
PMX 的着色(卡通阶梯、球面贴图、平坦环境光)在 glTF 里没有等价实现。
v0.2.5 起会补回双面、规范化 PBR 参数并清掉无关扩展; 想要最接近 MMD 的
平涂颜色, 把 MODEL_SHADING=unlit 写进 deploy/.env 后重新导入模型。
球面贴图与 toon 阶梯无法保留, 数量会记在模型的"转换说明"里。
- 列表/审核里的缩略图是"白模"(纯白模型)
v0.2.4 前的缩略图渲染器不采样贴图, 而 MMD 模型的 baseColorFactor 是白色。
升级到 v0.2.4 后重新生成缩略图: cd /opt/opendance/web-server &&
node scripts/reanalyze-models.mjs --url http://127.0.0.1:3000 --force
@@ -302,11 +328,12 @@ deploy/.env 初始化引导(deploy/init-env.sh)
cd web-server
npm run contracts:check # 契约版本一致性
npm run typecheck # TypeScript 严格检查
npm run test # 211 项单元测试 / 14 个文件(VMD 31、模型压缩包 24、
npm run test # 220 项单元测试 / 15 个文件(VMD 31、模型压缩包 24、
# 模型检查器 25、缩略图 8、骨骼过滤 8、
# 预处理 25、init-env 16、admin-port 16、
# access-log 9、VRM 检查器 6、.env 预检 12、
# Assimp 定位与安装 13、stats 容量与编码 12、缩略图贴图 6)
# Assimp 定位与安装 13、stats 容量与编码 12、缩略图贴图 6、
# MMD 材质对齐 9)
npm run build # 生产构建
npm run start:prod & # 启动
npm run test:smoke # 57 项端到端冒烟(需要数据库可连通)
@@ -364,6 +391,10 @@ deploy/.env 初始化引导(deploy/init-env.sh)
MODEL_CONVERT_PMX 压缩包内优先选用的 PMX 文件名(默认 "Hatsune Miku.pmx",
大小写不敏感); 找不到时按「格式优先级 -> 目录最浅 ->
文件最大」挑选
MODEL_SHADING 转换后模型的着色模式: pbr(默认, 标准 PBR 并按 PMX 参数修正
doubleSided/metallic/roughness)| unlit(写 KHR_materials_unlit,
颜色 = 贴图 x baseColorFactor, 与场景光照无关, 最接近 MMD
的平涂观感)
MODEL_CONVERT_TIMEOUT_MS
单次转换超时(毫秒, 默认 180000)
DEFAULT_MODEL_ID 可选: 显式指定默认模型 id; 不设置时按源码种子