AGAL
AGAL(Adobe Graphics Assembly Language)是Adobe开发的图形汇编语言,汇编语言是仅高于计算机二进制机器码的低级语言,可以精确地操控机器硬件比如可编程显卡,PC的Dirext9、MAC的OpenGL以及移动设备中的OpenGL ES 2都是可编程显卡,并且都支持AGAL。通过Adobe官方提供的编译器AGALMiniAssembler(实际上是一个AS类库),我们可以通过字符串指令来获得一个AGAL二进制流,再通过context3D上传给显卡的编程管线。对于顶点以及片段的运算都是通过AGAL交由显卡来处理的,这就是传说中的GPU硬件加速。),最新的测试版flash player 11中提供了可调用显卡资源来渲染图形API,即Molehill
1。属性寄存器
这些寄存器参考顶点着色器的VertexBuffer输入。因此,他们只能在顶点着色器中可用。
要通过正确的索引分配一个VertexBuffer到一个特定的属性寄存器,使用方法
Context3D:setVertexBufferAt()
在着色器中,访问属性寄存器的语法:va<n>,其中<n>是属性寄存器的索引号。
有一共有8个属性寄存器用于顶点着色器。
2。常量寄存器
这些寄存器是用来从ActionScript传递参数到着色的。这是通过Context3D::setProgramConstants()系列函数来实现。
在着色器中,这些寄存器的访问语法:
vc<n>,用于顶点着色器
fc<n>,用于像素着色器
其中<n>是常量寄存器的索引值。
有128个常量寄存器用于顶点着色器和28常量寄存器用于像素着色器。
3。临时寄存器
这些寄存器在着色器中,可以用于临时计算。
这些寄存器的访问语法:
vt<n> (vertex),用于顶点着色器
ft<n> (pixel),用于像素着色器
<n>是寄存器编号。
有8个用于顶点着色器,8个用于像素着色器。
4。输出寄存器
输出寄存器是在顶点和像素着色器存储其计算输出。此输出用于顶点着色器是顶点的剪辑空间位置。用于像素着色器是该像素的颜色。
访问这些寄存器运算的语法:
op,用于顶点着色器
oc,用于像素着色器
但显然只能一个输出寄存器用于顶点和像素着色器。
5。变寄存器
这些寄存器用来从顶点着色器传递数据到像素着色器。传递数据被正确地插入图形芯片,从而使像素着色器接收到正确的正在处理的像素的值。
以这种方式获取传递的典型数据是顶点颜色,或 纹理UV 坐标。
这些寄存器可以被访问的语法v <n>,其中<n>是寄存器编号。
有8个变寄存器可用。
6。纹理取样器
纹理采样寄存器是用来基于UV坐标从纹理中获取颜色值。
纹理是通过ActionScriptcall指定方法Context3D::setTextureAt()。
纹理样本的使用语法是:fs<n> <flags>,其中<n>是取样指数,<flags>是由一个或多个标记,用于指定如何进行采样。
<flags>是以逗号分隔的一组字符串,它定义:
纹理尺寸。可以是:二维,三维,多维数据集
纹理映射。可以是:nomip,mipnone,mipnearest,mipnone
纹理过滤。可以是:最近点采样,线性
纹理重复。可以是:重复,包装,夹取。
因此,举例来说,一个标准的2D纹理没有纹理映射,并进行线性过滤,可以进行采样到临时寄存器FT1,使用以下命令:
“tex ft1, v0, fs0 <2d,linear,nomip> “
变寄存器v0持有插值的纹理 UVs。
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 作 4×4 矩陣轉型後指定到輸出剪輯空間 (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
AS3中,编译AGAL指令须按照以下几个步骤:
1、创建AGALMiniAssembler类对象 (AGALMiniAssembler 是Adobe提供的用来将字符串格式的AGAL指令编译成二进制码的工具类),如:
var vertexShaderAssembler:AGALMiniAssembler = new AGALMiniAssembler();
var fragmentShaderAssembler:AGALMiniAssembler = new AGALMiniAssembler();
2、编译AGAL代码,如:
vertexShaderAssembler.assemble(Context3DProgramType.VERTEX,
"m44 op, va0, vc0\n" +
"mov v0, va0\n" +
"mov v1, va1\n" +
"mov v2, va2\n" );
fragmentShaderAssembler.assemble(Context3DProgramType.FRAGMENT,
"tex ft0, v1, fs0<2d, repeat, miplinear>\n" +
"mov oc, ft0\n" );
3、创建Shader,如:
var shaderProgram:Program3D = _context3D.createProgram();
4、将编译后的AGAL代码上载给Shader ,如:
shaderProgram.upload(vertexShaderAssembler.agalcode, fragmentShaderAssembler.agalcode);