AGAL 字节码必须使用 Endian.LITTLE_ENDIAN 格式。
字节码标头
AGAL 字节码必须以一个 7 字节标头开头。
A0000001A100 -- for a vertex program A0000001A101 -- for a fragment program
偏移量(字节数) | 大小(字节数) | 名称 | 说明 |
---|---|---|---|
0 | 1 | magic | 必须为 0xa0 |
1 | 4 | version | 必须为 1 |
5 | 1 | shader type ID | 必须为 0xa1 |
6 | 1 | shader type | 0 表示顶点程序;1 表示片段程序 |
标记
标头后直接跟任意数量的标记。每个标记的大小都为 192 位(24 字节),且格式始终为:
[opcode][destination][source1][source2 or sampler]
并不是每一个 opcode 都使用所有这些字段。不使用的字段必须设置为 0。
操作代码
[opcode] 字段的大小为 32 位,可具有以下值之一:
名称 | Opcode | 操作 | 说明 |
---|---|---|---|
mov | 0x00 | 移动 | 将数据从 source1 移动到 destination,按组件 |
add | 0x01 | 相加 | destination = source1 + source2,按组件 |
sub | 0x02 | 相减 | destination = source1 - source2,按组件 |
mul | 0x03 | 相乘 | destination = source1 * source2,按组件 |
div | 0x04 | 除以 | destination = source1 / source2,按组件 |
rcp | 0x05 | 倒数 | destination = 1/source1,按组件 |
min | 0x06 | 最小值 | destination = minimum(source1,source2),按组件 |
max | 0x07 | 最大值 | destination = maximum(source1,source2),按组件 |
frc | 0x08 | 分数 | destination = source1 - (float)floor(source1),按组件 |
sqt | 0x09 | 平方根 | destination = sqrt(source1),按组件 |
rsq | 0x0a | 平方根倒数 | destination = 1/sqrt(source1),按组件 |
pow | 0x0b | 幂 | destination = pow(source1,source2),按组件 |
log | 0x0c | 对数 | destination = log_2(source1),按组件 |
exp | 0x0d | 指数 | destination = 2^source1,按组件 |
nrm | 0x0e | 标准化 | destination = normalize(source1),按组件(仅生成一个 3 组件结果,目标必须遮罩为 .xyz 或更小) |
sin | 0x0f | 正弦 | destination = sin(source1),按组件 |
cos | 0x10 | 余弦 | destination = cos(source1),按组件 |
crs | 0x11 | 叉积 | destination.x = source1.y * source2.z - source1.z * source2.y destination.y = source1.z * source2.x - source1.x * source2.z destination.z = source1.x * source2.y - source1.y * source2.x (仅生成一个 3 组件结果,目标必须遮罩为 .xyz 或更小) |
dp3 | 0x12 | 点积 | destination = source1.x*source2.x + source1.y*source2.y + source1.z*source2.z |
dp4 | 0x13 | 点积 | destination = source1.x*source2.x + source1.y*source2.y + source1.z*source2.z + source1.w*source2.w |
abs | 0x14 | 取绝对值 | destination = abs(source1),按组件 |
neg | 0x15 | 求反 | destination = -source1,按组件 |
sat | 0x16 | 饱和 | destination = maximum(minimum(source1,1),0),按组件 |
m33 | 0x17 | 矩阵连乘 3x3 | destination.x = (source1.x * source2[0].x) + (source1.y * source2[0].y) + (source1.z * source2[0].z) destination.y = (source1.x * source2[1].x) + (source1.y * source2[1].y) + (source1.z * source2[1].z) destination.z = (source1.x * source2[2].x) + (source1.y * source2[2].y) + (source1.z * source2[2].z) (仅生成一个 3 组件结果,目标必须遮罩为 .xyz 或更小) |
m44 | 0x18 | 矩阵连乘 4x4 | destination.x = (source1.x * source2[0].x) + (source1.y * source2[0].y) + (source1.z * source2[0].z) + (source1.w * source2[0].w) destination.y = (source1.x * source2[1].x) + (source1.y * source2[1].y) + (source1.z * source2[1].z) + (source1.w * source2[1].w) destination.z = (source1.x * source2[2].x) + (source1.y * source2[2].y) + (source1.z * source2[2].z) + (source1.w * source2[2].w) destination.w = (source1.x * source2[3].x) + (source1.y * source2[3].y) + (source1.z * source2[3].z) + (source1.w * source2[3].w) |
m34 | 0x19 | 矩阵连乘 3x4 | destination.x = (source1.x * source2[0].x) + (source1.y * source2[0].y) + (source1.z * source2[0].z) + (source1.w * source2[0].w) destination.y = (source1.x * source2[1].x) + (source1.y * source2[1].y) + (source1.z * source2[1].z) + (source1.w * source2[1].w) destination.z = (source1.x * source2[2].x) + (source1.y * source2[2].y) + (source1.z * source2[2].z) + (source1.w * source2[2].w) (仅生成一个 3 组件结果,目标必须遮罩为 .xyz 或更小) |
kil | 0x27 | 丢弃(仅适用于片段着色器) | 如果单个标量源组件小于零,则将丢弃片段并不会将其绘制到帧缓冲区。(目标寄存器必须全部设置为 0) |
tex | 0x28 | 纹理取样(仅适用于片段着色器) | destination 等于从坐标 source1 上的纹理 source2 进行加载。在这种情况下,source2 必须采用取样器格式。 |
sge | 0x29 | 大于等于时设置 | destination = source1 >= source2 ? 1 : 0,按组件 |
slt | 0x2a | 小于时设置 | destination = source1 < source2 ? 1 : 0,按组件 |
seq | 0x2c | 相等时设置 | destination = source1 == source2 ? 1 : 0,按组件 |
sne | 0x2d | 不相等时设置 | destination = source1 != source2 ? 1 : 0,按组件 |
Destination 字段格式
[destination] 字段的大小为 32 位:
31.............................0 ----TTTT----MMMMNNNNNNNNNNNNNNNN
T = 寄存器类型(4 位)
M = 写入遮罩(4 位)
N = 寄存器编号(16 位)
- = 未定义,必须为 0
Source 字段格式
[source] 字段的大小为 64 位:
63.............................................................0 D-------------QQ----IIII----TTTTSSSSSSSSOOOOOOOONNNNNNNNNNNNNNNN
D = Direct=0/Indirect=1 表示直接使用 Q 并忽略 I,1 位
Q = 索引寄存器组件选择(2 位)
I = 索引寄存器类型(4 位)
T = 寄存器类型(4 位)
S = 重排(8 位,每个组件 2 位)
O = 间接偏移量(8 位)
N = 寄存器编号(16 位)
- = 未定义,必须为 0
Sampler 字段格式
tex opcode 的第二个源字段必须为 [sampler] 格式,大小为 64 位:
63.............................................................0 FFFFMMMMWWWWSSSSDDDD--------TTTT--------BBBBBBBBNNNNNNNNNNNNNNNN
N = 取样器寄存器编号(16 位)
B = 纹理详细级别 (LOD) 偏差,带符号整数,以 8 为单位递增。使用的浮点值为 b/8.0(8 位)
T = 寄存器类型,必须为 5,Sampler(4 位)
F = 滤镜(0=nearest、1=linear)(4 位)
M = Mipmap(0=disable、1=nearest、2=linear)
W = 环绕(0=clamp、1=repeat)
S = 特殊标志位(必须为 0)
D = 维度(0=2D、1=Cube)
程序寄存器
定义了以下寄存器类型:使用列出的值可在标记字段中指定寄存器类型:
名称 | 值 | 每个片断程序的数量 | 每个顶点程序的数量 | 用法 |
---|---|---|---|---|
属性 | 0 | 无 | 8 | 顶点着色器输入;从使用 Context3D.setVertexBufferAt() 指定的顶点缓冲区读取。 |
常数 | 1 | 28 | 128 | 着色器输入;使用 Context3D.setProgramConstants() 系列函数设置。 |
临时 | 2 | 8 | 8 | 用于计算的临时寄存器,无法从程序外部访问。 |
输出 | 3 | 1 | 1 | 着色器输出:在顶点程序中,输出的是剪辑空间位置;在片段程序中,输出的是颜色。 |
变化 | 4 | 8 | 8 | 在顶点着色器和片段着色器之间传递插补数据。将顶点程序的渐变寄存器用作片断程序的输入。根据与三角形顶点的距离插补计算所需的值。 |
取样器 | 5 | 8 | 无 | 片段着色器输入;从使用 Context3D.setTextureAt() 指定的纹理读取。 |