清单配置规范 (pack.json)

pack.json 格式 1 规范说明,涵盖多语言配置、材质分类规则(classes)与可调参数定义(params)。

清单文件概述

pack.json 是声明着色器包元数据、本地化描述、推荐适用模型、材质分类规则及用户调节滑块的 JSON 配置文件。MMDX12 在扫描加载着色器包时会优先读取并校验该文件。

{
  "format": 1,
  "id": "my_pack",
  "version": "1.0.0",
  "apiVersion": 1,
  "minAppVersion": "1.2.0",
  "name": { "ko": "내 팩", "en": "My Pack", "ja": "マイパック", "zh": "我的着色器" },
  "description": { "ko": "원신 풍 툰 셰이딩입니다.", "en": "Cel shading for anime models." },
  "recommendedFor": { "ko": "Genshin, Star Rail 공식 모델", "en": "Official HoYoverse MMD models" },
  "authors": [ { "name": "YourName", "role": "Shader", "url": "https://github.com/..." } ],
  "license": "MIT",
  "homepage": "https://...",
  "repository": "https://github.com/...",
  "tags": ["toon", "anime"],
  "classes": [
    { "class": "eye",  "match": ["目", "眼", "瞳", "eye", "Eye"] },
    { "class": "face", "match": ["顔", "颜", "face", "Face", "表情"] },
    { "class": "hair", "match": ["髪", "髮", "hair", "Hair"] },
    { "class": "skin", "match": ["肌", "皮肤", "skin", "Skin"] }
  ],
  "params": [
    { "key": "softness", "label": { "zh": "羽化过渡", "en": "Softness" }, "default": 0.1, "min": 0.0, "max": 1.0 }
  ]
}

字段详细规范

必填字段

  • version(字符串):语义化版本号(如 "1.0.0"),用于版本比较、更新提示及展示馆索引。
  • name(字符串或本地化对象):着色器包对外的显示名称。

身份标识与版本兼容

  • format(整数):清单配置格式版本,当前版本固定为 1。
  • id(字符串):由小写英文字母 a-z、数字 0-9、下划线 _ 和连字符 - 组成,最多 64 字符。若缺省则默认采用文件夹名称;对于已安装包,文件夹名必须与 id 保持一致。
  • apiVersion(整数,默认 1):目标着色器 API 版本。若高于当前软件支持的版本(目前为 2),则会被标记为“不兼容”并不予加载。
  • minAppVersion(字符串,可选):运行所需的最低 MMDX12 软件版本(如 "1.2.0")。

元数据与本地化多语言

  • 本地化字段:name、description、recommendedFor 以及参数中的 label 支持普通字符串或带有 ko、en、ja、zh 键的对象。
    • 回退机制:当前软件语言 -> en -> 普通字符串 -> ko -> 已定义的任意语言。
  • authors(数组):作者信息列表。每项包含 name(必填)、role(可选,如“着色器”、“本地化”等职责描述)和 url(可选,主页或主页链接,仅支持 http:// 或 https://)。为了向下兼容,亦支持旧版字符串格式 "author": "名字"。
  • license(字符串):SPDX 格式开源许可证(如 "MIT"、"CC-BY-4.0")。
  • homepage、repository(字符串):官方主页与源码仓库链接(仅支持 HTTP/HTTPS 协议)。
  • tags(字符串数组):检索标签(小写英文,最多 12 个)。

材质分类规则(classes)

不同制作者提供的 PMX 模型材质命名各异。着色器包通过 classes 匹配规则,将模型上的所有材质自动归类到 6 种标准材质类别:

  1. body(默认类别:未命中任何规则时的所有材质)
  2. skin(皮肤)
  3. face(面部)
  4. eye(眼部与眼瞳)
  5. hair(头发)
  6. weapon(武器、道具)

匹配机制

  • 规则数组自顶向下严格按顺序匹配。
  • 第一条命中的规则即为最终分类。
  • 将 match 数组内的每个关键字作为子字符串,与 PMX 材质的日文名称和英文名称进行包含关系比对。
"classes": [
  { "class": "eye",  "match": ["目", "眼", "瞳", "eye", "Eye"] },
  { "class": "face", "match": ["顔", "颜", "face", "Face", "表情"] },
  { "class": "hair", "match": ["髪", "hair"] },
  { "class": "skin", "match": ["肌", "skin"] }
]

在 HLSL 中,分类结果将通过 s.materialClass(取值为 PACK_BODY、PACK_SKIN、PACK_FACE、PACK_EYE、PACK_HAIR、PACK_WEAPON)传入,供代码进行条件分支处理。

参数滑块配置(params)

定义供用户在 UI 界面实时交互调节的浮点参数:

  • 参数上限:最多 16 个参数(对应 PackParam(0) 到 PackParam(15))。
  • 顺序映射:清单中的数组顺序与 HLSL 函数访问索引严格对应。
  • 属性:
    • key(字符串):参数持久化键名。版本升级时应保持该键名稳定,以保留用户已调好的预设。
    • label(字符串或多语言对象):在界面滑块前显示的标签文本。
    • default(浮点数):默认初始数值。
    • min、max(浮点数):滑块可调节的取值范围。
  • 保存策略:仅记录用户偏离默认值的参数项。未被触碰过的参数将在包作者更新默认值时自动跟进新版本数值。

着色器包贴图(textures,API 2)

有些观感无法只靠模型自带的贴图实现:游戏风格的卡通着色需要 LightMap、冷/暖色 Ramp、脸部 SDF、MatCap 或参数 LUT 等额外贴图。 着色器包在 pack.json 中声明这些贴图,并用 PackSampleTex 采样(参见着色器 API)。使用贴图的包请设置 "apiVersion": 2。

"apiVersion": 2,
"textures": [
  { "file": "textures/body_lightmap.png", "address": "clamp", "srgb": false },
  { "file": "textures/body_ramp.png",     "address": "clamp", "srgb": true }
]
  • file:相对于包目录的路径,仅允许 png、jpg、jpeg,不能使用 .. 或绝对路径。
  • address:"wrap"(默认)或 "clamp"。Ramp 必须使用 clamp:其受光端位于 u = 1.0,使用 wrap 会在那里采到阴影端。
  • srgb(默认 true):颜色贴图,采样结果为线性值,请勿再调用 SrgbToLinear。LightMap、SDF、LUT 等数据贴图请设为 false,返回原始存储值。
  • 限制:最多 16 张,单张不超过 4096 × 4096,整个包不超过 32 MB。
  • 数组顺序即 HLSL 中的索引(PackSampleTex(0, uv) 为第一项)。

用户贴图目录

从游戏中解包的贴图属于厂商的版权物,不能再分发。因此着色器包可以只发布 pack.json 和 surface.hlsl,由用户自备贴图: 在着色器管理界面中,每个声明了贴图的包都可以指定一个贴图目录。贴图按以下顺序查找:

  1. 用户贴图目录:相同的相对路径(textures/body_ramp.png),找不到时按文件名(body_ramp.png)
  2. 包目录
  3. 白色 1 × 1 替代贴图。包仍会正常编译和渲染,管理界面会显示缺失的贴图数量。

上架展示馆的包只能包含你有权再分发的贴图。

按角色指定目录与文件名后缀匹配

游戏贴图因角色而异,因此贴图目录也可以按角色指定(资源库面板、播放栏或工作室检查器中,着色器包滑块下方的“贴图目录”一行), 其优先级高于包级目录。在用户目录中,依次按相同相对路径、相同文件名查找,仍找不到时查找文件名以 _ + 声明名称结尾的文件 (不区分大小写,最短的名称优先)。只需声明共同的结尾,原始文件名即可直接使用: Body_Lightmap.png 会找到 Avatar_Girl_Pole_Hutao_Tex_Body_Lightmap.png。

按贴图分类

classes 规则还可以用 "texture" 匹配材质的漫反射贴图路径。游戏贴图跟随的是贴图图集而不是材质名称(画在头发图集上的帽子需要头发的 LightMap),因此这种方式更可靠:

{ "class": "hair", "texture": ["发", "髮", "髪", "hair"] }

只要 match 中的字符串出现在材质名称中,或 texture 中的字符串出现在贴图路径中,规则即匹配;仍以第一条匹配的规则为准。