Flash Stage3D Molehill 学习笔记(3)

  前面已经了解了一些Stage3D的基础与工作原理,今天我准备继续深入了解下隐藏于Stage3D API背后的神秘代码 AGAL。

  废话不多说直接进入主题,老规矩先搞清楚什么是AGAL? 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.
这个百度里以及很详细了,有兴趣可以去了解下 http://baike.baidu.com/view/6423021.htm
AGAL代码结构
  <opcode> <destination> <source1> <source2>
  <操作码>   <目标>       <来源1>     <来源2或样例>
  opcode:表示执行什么指令或函数,而这个指令或者函数被称作“操作码”。
  destination:表示运算的结果要去的“目的地”。
  source1与source2:数据源的位置。
  例: mov v0, v1 表示将存于 va1 中的值复制到 v0。
  AGAL有大约30种不同的操作码。完整的操作码列表如下:
  

名称 描述 说明

mov 移动 移动 source1 数据到 destination

add 相加 destination = source1 + source2

sub 相减 destination = source1 - source2

mul 相乘 destination = source1 * source2

div 相除 destination = source1 / source2

rcp 倒数 destination = 1 / source1

min 最小值 destination = minimum(source1 , source2)

max 最大值 destination = minimum(source1 , source2)

frc 取小数 destination = source1 - (float) floor(source1)

sqt 平方根 destination = sqrt(source1)

rsq 平方根倒数 destination = 1 / sqrt(source1)

pow 指数 destination = pow(source1 , source2)

log 2 为底的对数 destination = log_2(source1)

exp 2 为底的指数 destination = 2^source1

nrm 标准化 destination = normalize(source1)

sin 正弦 destination = sin(source1)

cos 余弦 destination = cos(source1)

abs 绝对值 destination = abs(source1)

neg 负值 destination = -source1

sat 饱和值 destination = maximum(minimum(source1 , 1) , 0)

kil 抛弃(只限片断着色器) 假如单一分量小于 0 便放弃绘图

tex 材质取样(只限片断着色器) 依据 source1 坐标从 source2 材质取样

sge 分量运算(set-if-greater-equal) destination = source1 >= source2   1 : 0

slt 分量运算(set-if-less-than) 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 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 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 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)

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

AGAL Registers 缓存器

缓存器 定义 权限

顶点着色器 片断着色器 AS3编译器

vc0 - vc127 顶点矩阵常量 读 写

va0 - va7 顶点缓冲属性 读 写

vt0 - vt7 顶点临时变量 读/写

op 顶点着色器最终输出的对象 写

v0 - v7 变量 写 读

fc0 - fc27 片断常量 读 写

ft0 - ft7 片断临时变量 读/写

fs0 - fs7 片断纹理采样器 读/写

oc 片断着色器最终输出的对象 写

 什么是寄存器:
  <destination>、<source1>与 <source2> 都被称为“寄存器”。也以把它理解成 AS3中的变量,它是用来存储数据的地方。它们各自指向一小块显存,由于进行过优化,因此访问速度非常快。为了达到最快的速度,AGAL所提供的寄存器是有数量限制的。当你开始编写那些更为复杂的着色器时,你就会经常把它们用光,而不得不提出创出新的方法就是重用寄存器。
  从String到Vector3D再到Bitmap,AS3变量有着各种各样的数据格式。但与此相反,寄存器全部都是128bit的容量,并且包含有4个浮点数。这4个值又被称为4个分量。可以通过使用x,y,z,w或者r,g,b,a来单独访问一个分量。每个操作码都是按“分量形式”的方式执行指令。这意味着它们会按顺序,把寄存器分量一个一个的分别加到一起。
  例:add va0, va1; 这句指令执行了add 操作码,显卡就会把 va0.x和va1.x相加,然后是 va0.y 和 va1.y,va0.z 和 va1.z,最后是 va0.w 和 va1.w。
  假设 va0 = (20,50,10,0);
     va1 = (50,5,0,1);
  则执行add指令结果 = (70,55,10,1)
 
Attribute Registers  属性寄存器

这些寄存器涉及顶点着色器的输入VertexBuffer。因此,他们只可用在顶点着色器。

为了指派一个VertexBuffer到指定的属性寄存器,在这个函数中使用正确的索引号Context3D::setVertexBufferAt()。

从着色器中访问该属性寄存器的语法:va<n>,其中<n>是属性寄存器的索引号。

总共有8个用于顶点着色器的属性寄存器。

Constant Registers 常量寄存器

这些寄存器是为了从ActionScript传递参数到着色器。通过Context3D::setProgramConstants()函数完成。

从着色器中访问这些寄存器的语法:vc<n>,用于顶点着色器,fc<n>,用于像素着色器,其中<n>是常量寄存器的索引号。
有128个用于顶点着色器和28个用于像素着色器的常量寄存器。

Temporary Registers  临时寄存器

这些寄存器供着色器在临时计算时使用。
访问它们的语法:vt<n>(点)和 ft<n> (像素),其中<n>是寄存器的序号。
有8个可用于顶点着色器,8个可用于像素着色器。
Output Registers 输出寄存器

输出寄存器存储顶点和像素着色器的计算输出。对于顶点着色器是一个顶点剪辑空间的位置。对于像素着色器是该像素的颜色。
访问这些寄存器的语法:op,用于顶点着色器,oc,用于像素着色器。
显然只有一个用于顶点和像素着色器的输出寄存器。
 Varying Registers 变量寄存器
这些寄存器用来从顶点着色器向像素着色器传递数据。
这些寄存器用来传递从顶点​​着色器到像素着色器的数据。所传数据被GPU转换,从而使像素着色器接收到正确的值,用于正在处理的像素。
用这种方法传递的典型数据是顶点的颜色或纹理的UV坐标。
访问这些寄存器的语法:v<n>,其中<n>是寄存器序号。
有8个变量寄存器可用。

Texture Samplers  纹理采样寄存器
纹理采样寄存器是用来接收从基于UV坐标系的纹理中的颜色值。
纹理的指定通过ActionScript使用方法 Context3D::setTextureAt()。
纹理采样的使用语法是:ft<n> <flags>,其中<n>是采样序号,<flags>是一个或多个用于指定应如何取样的标志集。

<flags>是一个以逗号分隔的字符串集,其定义是:

纹理维度。可以是:2d, 3d, cube
多重材质映射。可以是:nomip, mipnone, mipnearest, mipnone
纹理滤镜。可以是:nearest, linear
重复纹理。可以是:repeat, wrap, clamp.
好了,举例来说,一个标准的没有多重材质映射的2D纹理,进行线性滤镜采样到临时寄存器ft1中,用下行:
“tex ft1, v0, fs0 <2d,linear,nomip> “
其中变量寄存器v0保存以内插值替换的纹理UV坐标。
顶点和像素着色器例子解释
现在我们返回到着色器的例子,并解释其运作。
我们假设顶点在VertexBuffer中包含着顶点的位置,偏移量是0,纹理的UV偏移量是3。
我们希望我们的顶点着色器转换顶点位置到剪辑空间里,并传递UV到像素着色器。
执行以下代码:
m44 op, va0, vc0 // pos to clipspace
mov v0, va1 // copy uv
第一行执行了在输入顶点,va0,和从模型空间到剪辑空间的变换矩阵之间的4×4矩阵乘法,我们假定已从ActionScript写入到常量寄存器0中,vc0。
用下面的方法可将此矩阵写入到着色器:
Context3D::setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, matrix, true );
着色器的第二行,复制顶点UV数据到变量寄存器0,V0,因此,它可以获得修正,并传递到像素着色器。
像素着色器采样纹理,并复制颜色到输出寄存器。
tex ft1, v0, fs0 <2d,linear,nomip>
mov oc, ft1
好了,这个顶点/像素着色器刚刚将三维模型转换到二维屏幕上,并进行了纹理映射。
这就是我们的第一个顶点和像素着色器!
原文地址:https://www.cnblogs.com/ch06src/p/3132396.html