luanti API 纹理修饰器
纹理修饰器
纹理修饰器是一串告诉 Luanti 如何处理图片的字符串,除动态媒体外,它是运行时动态生成纹理的唯一方式。
它也能用来简化模组,批量生成重复纹理,比如不同颜色的工具贴图。
ℹ️ 说明
纹理修饰器和硬件着色功能部分重叠。优先使用硬件着色,更灵活、产生的冗余纹理更少。
性能问题
- 所有纹理在 CPU 生成,不在 GPU,速度慢,可能短暂卡住客户端线程
- 纹理修饰器会永久留在客户端内存
- 生成新修饰器时不会复用缓存
- 解析器可能出现至少是二次方的时间复杂度
建议:
- 尽量静态使用纹理修饰器
- 动态生成的纹理越少越好,避免撑爆客户端缓存
- 不要短时间内让客户端大量生成高开销纹理
- 尽量别写又长又复杂的修饰器
已知 Bug
- 大型修饰器可能卡死客户端
- 部分修饰器可能导致越界内存读取,例:
[lowpart:0:blank.png - 越界像素通常被当成纯白色(#FFFFFFFF)
- 非法修饰器可能导致客户端段错误
- 语法错误的部分可能被静默忽略
材质包(Texture Packs)
- 纹理修饰器可用于方块、物品的纹理覆盖
- 修饰器生成的纹理不能被材质包直接替换(只能通过覆盖替换),只有基础纹理可以
- 部分修饰器依赖固定分辨率,低分辨率材质包通常可以向上缩放,高分辨率则需要缩小
💡 小贴士
用 [resize 强制缩放到你需要的尺寸,能更好地兼容各种材质包。
在 Lua 中使用
API
core.inventorycube(top, left, right)
唯一自带的纹理修饰工具函数。
参数:
top、left、right:字符串,对应面的纹理修饰器
返回:
生成 [inventorycube{<top>{<left>{right> 格式修饰器,并自动转义。
字符串写法
Lua 有三种字符串写法:双引号、单引号、长字符串。
纹理名一般不包含引号,所以用哪种都行。
引号字符串里写反斜杠需要转义:
a.png^[mask:b.png\^c.png
写成"a.png^[mask:b.png\\^c.png"长字符串用双方括号
[[...]],内部不需要转义,非常适合写纹理修饰器:[[[combine:1x1:0,0=a.png]]
💡 小贴士
可以用元方法实现一套优雅的 DSL,帮你自动转义与格式化。
语法
⚠️ 警告
纹理修饰器只在客户端解析,服务器不做校验。出错轻则显示错误纹理,重则直接崩溃。
务必保证语法正确、数值合法。
基础规则:
<...>表示必填参数[...]表示可选- 所有范围都是闭区间(包含起止值)
叠加(Overlaying)
用 ^ 符号实现叠加:
- 右侧纹理覆盖在左侧之上
- 支持链式:
a^b^c - 叠加前,像素少的纹理会缩放到多的那一张
- 正确处理 Alpha 混合
参数转义
用反斜杠 \ 转义,只在**组合型修饰器**内需要。
必须转义:^、:、\。
嵌套转义需要翻倍反斜杠:n 层嵌套需要 2ⁿ 个反斜杠。
inventorycube 转义规则特殊:
^换成&- 不支持嵌套
示例转义函数:
1 | local function escape_argument(texture_modifier) |
分组(括号)
用括号 () 强制优先计算,只对叠加有效。
不能在组合修饰器里用来分隔参数,必须用转义。
错误:a^[lowpart:1:(b^c)
正确:a^[lowpart:1:b\^c
修饰器列表
所有修饰器都生成新纹理,不修改原图。
组合型修饰器(多图合并)
[mask:按位遮罩[lowpart:贴下半部分[combine:按坐标拼贴多图[inventorycube:生成物品栏立方体
基础纹理修饰器
<base>^[brighten
每个像素颜色与白色50% 混合,提亮。
<base>^[noalpha
把 Alpha 通道强制设为 255(完全不透明)。
<base>^[makealpha:<r>,<g>,<b>
把 RGB 完全匹配的像素设为透明。
<base>^[opacity:<ratio>
透明度整体缩放,ratio 0~255。
<base>^[invert:<mode>
反色通道,mode 可包含 r/g/b/a。
<base>^[transform<transforms>
旋转/翻转,支持数字或名称(不区分大小写):
| 数字 | 名称 | 效果 |
|---|---|---|
| 0 | I | 不变 |
| 1 | R90 | 逆时针90° |
| 2 | R180 | 逆时针180° |
| 3 | R270 | 逆时针270° |
| 4 | FX | 水平翻转 |
| 5 | FXR90 | 水平翻转+逆时针90° |
| 6 | FY | 垂直翻转 |
| 7 | FYR90 | 垂直翻转+逆时针90° |
<base>^[verticalframe:<framecount>:<frame>
按帧数垂直裁切动画纹理。
⚠️ framecount=0 会除零崩溃客户端。
<base>^[crack[<opacity>]:[<framecount>:]<tilecount>:<frame>
在纹理上叠加破损动画(crack_anylength.png)。
opacity填 o → 只在完全不透明区域显示破损tilecount:分块数,通常 1frame:当前破损帧
<base>^[sheet:<w>x<h>:<x>,<y>
从精灵图中截取一格。
<base>^[multiply:<color>
RGB 通道与颜色相乘,忽略 Alpha。
<base>^[colorize:<color>[:<ratio>]
颜色混合:
ratio0~255:0=原图,255=纯颜色- 填
alpha:按纹理自身透明度混合
<base>^[mask:<texture>
按位与遮罩,只保留重叠不透明部分。
<base>^[lowpart:<percent>:<texture>
把另一张图的下百分之 N 贴上来。
基础纹理生成器(不需要底图)
[png:<data>
从 base64 编码的 PNG 生成纹理。
1 | "[png:" .. core.encode_base64(core.encode_png(w, h, data)) |
⚠️ Luanti 5.4 及以下不支持,用作方块贴图可能崩溃。
[combine:<w>x<h>:<x>,<y>=<tex>:...
创建指定尺寸的透明图,按坐标拼贴其他纹理。
背景:透明黑 #00000000。
[inventorycube{<top>{<left>{<right>
用三张图生成物品栏立方体图标。
尺寸公式:9 * max(4, min(64, 2^ceil(log2(max_size))))
实用示例
破损方块
default_stone.png^[crack:1:2
裁切
裁掉左上6px(16x16→8x8):[combine:8x8:-8,-8=default_stone.png
进度条
嵌套 combine(分辨率相关)
1 | [combine:256x48:0,0=bg.png:0,0=[combine\:128x48\:0,0=bar.png |
lowpart + 旋转(分辨率无关)
1 | bg.png^[transformR90^[lowpart:50:bar.png\^[transformR90^[transformR270 |