换装示例验证记录与性能基线¶
本次实现与验证(2026-10-08)¶
本次改动提供真实模型的换纹理、换衣服模型和 MC 原生手持武器示例,所有穿搭均带上
用户提供的 13 号头发。公共数据由通用 Model、Skeleton、材质实例与组装接口组成。
| 改动 | 作用 |
|---|---|
WardrobeExample |
将用户素材接入现有 Reader,演示材质帧切换、模型替换、缓存复用与右手首持剑 |
KsgPmxLoader |
图集纹理 ID 由压缩包、PMX entry、贴图 entry 共同生成 SHA-256,修复跨压缩包同名素材串图 |
KsgPmxTextureIdentityTest |
覆盖不同压缩包、不同模型/贴图、Unicode 名称及旧字符串 hash 碰撞 |
| Iris 顶点上传与 MC 渲染栈 | 显式补齐中间 UV、切线和实体属性,支持工作线程与局部更新;渲染异常时用 finally 恢复 PoseStack |
| Shader 冒烟入口 | 可选真实 shader pack,验证活跃 Iris pipeline;默认只输出通过/失败日志,不截图、不采样性能 |
ModelAssemblyProbe |
增加带头发的 RibbonDress 短袖/长袖基准,记录 JVM PID、Java 版本与堆上限 |
| 本地素材准备脚本 | 将已解压素材转为本地资源包,可追加启用配置,保留其他资源包 |
| 性能汇总脚本 | 校验三个独立 JVM 的报告并仅输出 Markdown,不生成 HTML 或额外汇总 JSON |
| Gradle 与 API 文档 | 添加 opt-in 示例/自动验收参数、运行步骤和性能解释 |
本次提交范围为上述源码、测试、脚本与 API Markdown 文档。模型、贴图、资源包、存档、 截图、HTML、原始 JSON 报告、日志及 build 产物不纳入提交。
验证环境为 macOS / aarch64、Apple M3 Max、Java 21.0.3、Minecraft 1.21.1、NeoForge 21.1.203。 客户端加载 Iris 1.8.12 / Sodium 0.6.13。此前截图与性能观测使用 disabled 配置; 另用 BSL 8.2.04 跑通启用 shader pack 的六阶段冒烟检查。验证范围限于该环境与此 shader pack。
| 验证 | 结果 |
|---|---|
renderingReleaseCheck |
通过 |
modelUnitTest |
811 个用例,0 失败、0 错误、3 个条件跳过 |
renderGlTest |
13 组通过;真实配套素体/长裙的 21,259 个顶点通过 CPU/GPU 蒙皮对比 |
| 本地 PMX 探针 | 三次 JVM 均成功加载全部 92 个 PMX,0 加载失败 |
| 带头发的真实客户端示例 | WARDROBE_EXAMPLE_PASS,180 帧、61 次原生物品提交 |
| BSL 8.2.04 shader 路径 | WARDROBE_SHADER_SMOKE_PASS,六阶段全部走完,实际进入 IrisRenderingPipeline,未回退到无 shader |
客户端依次验证原配色、Rose 配色、长袖模型、切回短袖、MC 持剑和手腕旋转。
纹理切换保持同一个 Model;模型切换后换回短袖,取得第一次的同一个组装 Model,
build 计数不增加。新 session 总计构建两套组装模型。
这里的换回操作由穿搭注册表复用已解析结果,底层组装缓存 hits 为 0、builds 为 2,
不会把注册表复用错误计入底层 cache hit。
本机性能结果(2026-10-08)¶
分别运行三个独立 JavaExec JVM,PID 为 73993、74024、74050,测量顺序为
uncached-first、cached-first、uncached-first。Java runtime 为 21.0.3+10-LTS,
每次最大堆配置为 4 GiB。
以下结果为各 JVM 批次均值 p50 的中位数。未缓存组装包含公共几何/骨架组装工作; 热缓存两列分别测量重新构建请求再查缓存、复用已有请求只查缓存。 文件解析、贴图解码、GPU 蒙皮与绘制均不计入这些 CPU 组装指标。
| 用例 | 顶点 | 骨骼 | 未缓存组装(ms) | 构建请求+热缓存(µs) | 已有请求查缓存(µs) |
|---|---|---|---|---|---|
| Ayuchan 配套素体+长裙 | 21,259 | 316 | 70.168 | 7.400 | 0.263 |
| 素体+RibbonDress 短袖+13 号头发 | 21,397 | 263 | 60.738 | 3.015 | 0.041 |
| 素体+RibbonDress 长袖+13 号头发 | 22,069 | 263 | 63.751 | 2.286 | 0.040 |
| 素体+1 份真实小衣物 | 8,806 | 181 | 34.303 | 4.105 | 0.063 |
| 素体+10 份重复小衣物 | 12,955 | 694 | 41.089 | 20.289 | 0.093 |
| 素体+100 份重复小衣物 | 54,445 | 5,824 | 125.227 | 131.003 | 0.730 |
100 份压力用例重复同一个 461 顶点的小衣物,仅共享绑定兼容的骨骼;其余骨骼独立命名。 该结果不代表 100 件不同衣服已经拟合到素体,也不能换算为游戏 FPS 提升。 批次均值的 p50 不等于逐调用延迟分布,已有请求的缓存查询不等于整次换装。
实际客户端中还记录了以下单次 CPU 调用耗时,它们没有预热统计:
| 实际操作 | 单次 CPU 观测(ms) |
|---|---|
| 短袖切换 Rose 纹理 | 0.087 |
| 替换为长袖模型(含实例与 backend 挂载) | 289.673 |
| 换回缓存的短袖模型(含实例与 backend 挂载) | 171.290 |
| 短袖切回 Blue 纹理,两次观测 | 0.073 / 0.014 |
CPU 组装缓存能够避免再次组装同一几何与骨架,仍会创建新的 ModelInstance 和 backend 渲染资源。本次缓存未消除整次换装的这部分开销;上表中的单次调用也不是 GPU 或整帧耗时。
当前适配与验证边界¶
RibbonDress 与该素体的同名骨骼绑定位置不同,衣服与头发保留各自的独立绑定骨架。 本例不启用物理,也不执行全身动画;未实现自动体型拟合或骨骼重定向,不能据此保证 任意服装都无穿插。Ayuchan 配套长裙对照使用严格兼容的共享骨骼。
手持物品使用真实右手首 Anchor 与原生 ItemRenderer,不修改玩家物品栏。 本次客户端实际验收的是 Diamond Sword;Iron Pickaxe 是示例提供的另一个选项。 穿戴防具的 humanoid armor layer、其他 shader pack 与其他操作系统未在此示例中验收。 BSL 路径只验证能跑通,不将此解释为新的画质验收或性能测量。
交互命令和独立预览窗口入口已提供;上述客户端实测使用自动 headless Free Camera 输出, 不将其解释为本次重新验证了独立窗口操作。
启用 shader pack 的冒烟验证¶
使用已有本地 shader pack,例如 BSL 8.2.04;相对路径从仓库根目录解析。
./gradlew :modules:modelling:runClientHeadless \
-PkasugaClientDirectory=/tmp/kasuga-wardrobe-client \
-PkasugaQuickPlayWorld=wardrobe \
-PkasugaWardrobeShaderSmoke=true \
-PkasugaWardrobeShaderPack=/absolute/path/to/BSL_v8.2.04.zip
kasugaWardrobeShaderSmoke=true 自动启动同一套带头发的六阶段示例,不需要再开启
kasugaWardrobeDemo。在真实模型与物品渲染阶段检查当前 Iris pack 非空、shader pack 正在使用,
且实际 pipeline 为 IrisRenderingPipeline;只有阶段全部完成并通过 GL 检查才记录
WARDROBE_SHADER_SMOKE_PASS。失败记录 WARDROBE_SHADER_SMOKE_FAIL,不把 Gradle
退出成功当作 shader 验收成功。
该模式默认不读取像素、不保存图片/JSON、不记录操作耗时;不能同时打开 kasugaWardrobeCapture。
仅使用相机自己的 shader session,不将 BSL 设为主视角 shader pack。
如需查看实际结果,追加 -PkasugaWardrobeShaderPreview=true,只在持剑阶段保存一张
debug/wardrobe-example/shader-preview.png,仍不采样性能。图片为本地查看用,不纳入提交。
本机 BSL 8.2.04 路径已完成六阶段,Iris OIT 正常启用,无模型上传失败、矩阵栈异常或 无 shader 回退。因用户要求查看结果,另外取了一张持剑画面;原无 shader 的截图和性能报告未被覆盖。 这项验证确认运行路径通畅,不证明其他 shader pack、其他平台或最终画质均已通过。
性能展示¶
用 modelAssemblyProbe 连续运行三次独立 JavaExec JVM,
顺序交替为 uncached-first、cached-first、uncached-first,报告路径每次不同。
除了配套长裙和 1/10/100 份重复小衣物,探针还会测量本例的素体、RibbonDress 短袖/长袖与头发组装。
完成后运行:
python3 scripts/summarize-wardrobe-example.py \
--capture /tmp/kasuga-wardrobe-client/debug/wardrobe-example \
/tmp/wardrobe-bench-1.json /tmp/wardrobe-bench-2.json /tmp/wardrobe-bench-3.json
仅输出同目录的 summary.md;--output /path/to/report.md 可指定 Markdown 路径。
汇总文件不依赖图片、HTML 或额外汇总 JSON。表格展示三个 JVM 各自批次均值 p50 的中位数,并区分未缓存组装、构建请求再查热缓存、
已有请求查热缓存。输入解析、贴图解码、GPU 蒙皮和绘制均不计入这些 CPU 组装指标。
100 份压力用例重复同一件真实小衣物,不能解释为 100 件不同且已适配的衣服。
客户端报告中的 operations 是少数实际操作的 CPU 观测值;模型切换包含实例与 backend 挂载,
不能与上述预热基准或 GPU/整帧性能混用。性能数字应以本机实际生成报告为准。
本文是验证记录与性能基线篇。素材准备、可交互运行与自动截图验收的配方见 真实素材换装示例。