跳到主要内容

第 5 章:PAL0 区段

Directory Tag: PAL0
作用范围: 全局区段,chunkId = -1
必须性: 必须存在且仅存在一次
允许 Codec: RAW8

PAL0 定义体素 Palette Index 到颜色与基础材质属性的映射。VOX0 只保存一个 uint8 索引;其实际颜色和属性必须通过 PAL0 得到。

5.1 结构概览

PAL0 Payload 由 16 字节 Header 和 entryCount 个固定 8 字节颜色条目组成:

OffsetSizeTypeFieldDescription
02uint16paletteVersion必须为 1
22uint16headerSize必须为 16
42uint16entryCount已定义的非空颜色条目数,范围 0..255
62uint16entrySize必须为 8
84uint32paletteFlagsVFP 1.3 必须为 0
124uint32reserved必须为 0

随后是按 Palette Index 严格升序排列的条目。Payload 总长度必须为:

16 + entryCount × 8

每个条目布局如下:

OffsetSizeTypeFieldDescription
01uint8indexPalette Index,必须为 1..255
11uint8r红色,sRGB 0..255
21uint8g绿色,sRGB 0..255
31uint8b蓝色,sRGB 0..255
41uint8aAlpha,0..255
51uint8materialFlags基础材质标志
61uint8emission自发光强度,线性 0..255
71uint8reserved必须为 0

5.2 Palette Index 规则

索引 0 永远表示空体素,不得在 PAL0 中写入条目。索引 1..255 可被 VOX0 引用。

每个索引只能出现一次;条目必须按 index 升序存储,但不要求连续。例如只定义索引 14128 是合法的;VOX0 只能引用已定义的索引。

META.paletteEntryCount 必须等于 entryCount。写入器应尽量连续分配索引,以减少调色板重排和便于后续编辑,但这不是合法性要求。

5.3 颜色与材质语义

r/g/b 是标准 sRGB 8 位颜色。a 是非预乘 Alpha;255 表示完全不透明,0 表示完全透明。

materialFlags 按位定义:

Bit名称含义
0TRANSLUCENT该颜色应按透明材质路径渲染
1UNLIT默认渲染可不受光照影响
2DOUBLE_SIDED生成面可按双面材质显示
3–7Reserved必须为 0

emission 为线性自发光强度,0 表示无自发光,255 表示该实现支持范围内的最大强度。具体亮度映射属于渲染器策略;渲染器必须保持相对大小而不改变原始字段。

透明或完全透明的颜色仍表示“非空体素”。空体素只能由 Palette Index 0 表示;不得用 a = 0 替代空体素。

5.4 编译与编辑规则

编译器将输入颜色映射到最多 255 个可引用条目。超过 255 种颜色时,编译器必须明确采用量化、分拆资产或拒绝编译;不得静默把不同颜色映射为同一索引。

编辑器修改某个条目的 RGBA 或材质属性时,所有引用该索引的体素语义都会改变,因此必须增加 META.sourceRevision、重新计算 Source Hash,并使相关缓存失效。只要 Palette Index 到颜色映射改变,即使 VOX0 字节未改变,也属于权威数据修改。

5.5 验证规则

验证器必须检查:

  • codec = RAW8,Header 长度和 Entry 长度分别为 168
  • entryCount <= 255,Payload 长度精确匹配;
  • paletteVersion = 1paletteFlags = 0,保留字段为 0
  • 所有条目索引在 1..255,严格升序且不重复;
  • 每条 materialFlags 的保留位为 0,条目保留字段为 0
  • META.paletteEntryCount == entryCount
  • 每个 VOX0 出现的非零索引均有对应条目。

PAL0 缺失、损坏或被 VOX0 引用了未定义索引时,读取器必须拒绝资产。


本章总结

PAL0 通过紧凑、显式且稳定的索引映射,将 VOX0 的单字节体素值解释为颜色和基础材质属性。它是权威数据,不能由渲染缓存替代。