AGAL Registers 暂存器:

vc0 - vc127 : vertex constant, read only in Vertex Shader, write only in AS3
va0 - va7 : vertex attribute, read only in Vertex Shader, write only in AS3
vt0 - vt7 : vertex temporary, read/write in Vertex Shader
op : vertex output position, write only in Vertex Shader
v0 - v7 : varying, write only in Vertex Shader, read only in Fragment Shader
fc0 - fc27 : fragment constant, read only in Fragment Shader, write only in AS3
ft0 - ft7 : fragment temporary, read/write in Fragment Shader
fs0 - fs7 : fragment texture sampler, read/write in Fragment Shader
oc : fragment output color, write only in Fragment Shader

暂存器感觉有点象是高阶语言的变量
根据用途也有区分写入权限等等

从 AS3 只能写入资料到 vc, va, fc
vc, va, vt, op 暂存器只能用于顶点着色器,fc, ft, fs, oc 暂存器只能用于片段着色器
v 暂存器则是唯一可以在顶点着色器设定,然后从片段着色器读取的沟通方式

op 是顶点着色器最后输出的对象
oc 是片段着色器最后输出的对象

而暂存器的数量也是有限制的
vc 最多有 128 个可用,fc 也有 28 个可用
其它的大多只有 8 个可用
op, oc 应该是各只有一个了

以上这些暂存器每个资料容量似乎都是 float4
可以用 x, y, z, w 单独使用个别 float

从 AS3 设定 vc, va, fc 暂存器的方式

以下是透过 Context3D 从一个 Matrix3D 设定 vc0 - vc3
因为一个暂存器大小是 float4,而 Matrix3D 是 4x4
所以从 0 开始设下去就等于设定了 vc0 - vc3

cxt3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, new Matrix3D());

只要将第一个参数改为 FRAGMENT 就变成设定 fc 暂存器

cxt3D.setProgramConstantsFromMatrix(Context3DProgramType.FRAGMENT, 0, new Matrix3D());

va 暂存器设定方式

要先用 Context3D 建立 VertexBuffer,并且指定顶点数量与每个点资料量 (一个资料 32bit)
以下建立四个顶点,每个顶点 32bit * 5

var vertexBuffer:VertexBuffer3D = cxt3D.createVertexBuffer(4, 5);
vertexBuffer.uploadFromVector(Vector.<Number>([        
-1 ,  1 , 0 , 0 , 0 ,        
-1 , -1 , 1 , 0 , 0 ,         
 1 , -1 , 1 , 0 , 1 ,         
 1 ,  1 , 0 , 0 , 1 ]), 0, 4);
// 将顶点资料的 0-1 个 32bit 资料设定到 va0 的 x , y
cxt3D.setVertexBufferAt(0, vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_2);
// 将顶点资料的 2-4 个 32bit 资料设定到 va1 的 x , y , z
cxt3D.setVertexBufferAt(1, vertexBuffer, 2, Context3DVertexBufferFormat.FLOAT_3);

vc, va, fc 都可以从 AS3 设定,主要的差异在哪?

vc, fc 算是常数值,对于单次着色时的每个点,数值都是固定的
va 对于单次着色时的每个点,数值会依照 index buffer 内的 index 值,内插出 vertex attribute 数值来使用

AGAL Opcode 指令:

基本语法
[opcode] [destination] [source1] [source2 or sampler]
没有使用到的栏位必须设为 0 (应该是指 bytecode)

mov  move        分量移动     移动 source1 资料到 destination
add  add         分量相加     destination = source1 + source2
sub  subtract    分量相减     destination = source1 - source2
mul  multiply    分量相乘     destination = source1 * source2
div  divide      分量相除     destination = source1 / source2
rcp  reciprocal  分量倒数     destination = 1 / source1
min  minimum     分量最小值    destination = minimum(source1 , source2)
max  maximum     分量最大值    destination = maximum(source1 , source2)
frc  fractional  分量取小数    destination = source1 - (float) floor(source1)
sqt  square      分量平方根    destination = sqrt(source1)
rsq  recip. root 分量平方根倒数 destination = 1 / sqrt(source1)
pow  power       分量指数      destination = pow(source1 , source2)
log  logarithm   2 为底分量对数 destination = log_2(source1)
exp  exponential 2 为底分量指数 destination = 2^source1
nrm  normalize   分量标准化    destination = normalize(source1)
sin  sine        分量正弦      destination = sin(source1)
cos  cosine      分量余弦      destination = cos(source1)

abs  absolute    分量绝对值    destination = abs(source1)
neg  negate      分量负值      destination = -source1
sat  saturate    分量饱和值    destination = maximum(minimum(source1 , 1) , 0)



kil  kill / discard (fragment shader only)
   假如单一分量小于 0 便放弃绘图
   If single scalar source component is less than zero, fragment is discarded and not drawn to the frame buffer.
   The destination register must be all 0.

tex  texture sample (fragment shader only)
   依据 source1 坐标从 source2 材质取样
   destination = load from texture source2 at coordinates source1.
   In this source2 must be in sampler format.

sge  set-if-greater-equal
   分量运算,假如 source1 大于等于 source2,目标为 1,否则目标为 0
   destination = source1 >= source2 ? 1 : 0

slt  set-if-less-than
   分量运算,假如 source1 小于 source2,目标为 1,否则目标为 0
   destination = source1 < source2 ? 1 : 0


crs  cross product 矢量外积
   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
 
dp3  dot product  矢量内积
   destination = source1.x * source2.x + source1.y * source2.y + source1.z * source2.z

dp4  dot product  矢量内积
   destination = source1.x * source2.x + source1.y * source2.y + source1.z * source2.z + source1.w * source2.w


m33 multiply    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)

m44 multiply    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 multiply    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)

从 AGALMiniAssembler 里面看到还有这些 opcode
ifz, inz, ife, ine, ifg, ifl, ieg, iel, els, eif, rep, erp, brk, sgn
不过实际测试发现在目前这版 Flash Player 尚未支援

Error: Error #3621: AGAL validation failed: Invalid opcode, ifg is not implemented in this version at token 2 of fragment program.

AGAL 基本语法:

vc0, va0 作 4x4 矩阵转型后指定到输出剪辑空间 (output clipspace)

m44 op, va0, vc

以上语法等于以下个别分量的单独作内积

dp4 op.x, va0, vc0
dp4 op.y, va0, vc1
dp4 op.z, va0, vc2
dp4 op.w, va0, vc3

从 va1 复制到 v0 给 fragment shader 使用

mov v0, va1

等于

mov v0, va1.xyzw

注意 xyzw 顺序

mov v0, va1.yxzw

实际上是等于

mov v0.x, va1.y
mov v0.y, va1.x
mov v0.z, va1.z
mov v0.w, va1.w