AGAL的解释和使用
在stage3D这个最底层的flash3D的使用时,真的说实话真的要想看到我们想看到的任何一个模型真的很蛋疼,既要给什么顶点着色器和片段着色器上传信息,又得上传什么纹理等等可以参考我的关于stage3D的第一篇日志:第一个关于stage3D的HelloWorld,是不很奇葩呀,反正很头疼的!
这篇日志就真正说说那个着色其中的AGAL的使用,看上去就他妈的是什么汇编语言与寄存器打交道。下来就来打开这个蛋疼的AGAL吧。
在百度百科中对AGAL的定义是这样的:
AGAL(Adobe Graphics Assembly Language)是Adobe开发的图形汇编语言,汇编语言是仅高于计算机二进制机器码的低级语言,可以精确地操控机器硬件比如可编程显卡,PC的Dirext9、MAC的OpenGL以及移动设备中的OpenGL ES 2都是可编程显卡,并且都支持AGAL。通过Adobe官方提供的编译器AGALMiniAssembler(实际上是一个AS类库),我们可以通过字符串指令来获得一个AGAL二进制流,再通过context3D上传给显卡的编程管线。对于顶点以及片段的运算都是通过AGAL交由显卡来处理的,这就是GPU硬件加速。
AGAL的使用:
- 基本语法:
<操作码> <目标寄存器> <源寄存器1> ... <源寄存器2>
2. AGAL中的可用寄存器:
- 目标寄存器op、oc:分别针对顶点寄存器和片段寄存器的输出信息;
- 临时寄存器vt、ft:分别是暂存顶点信息和片段信息的,也就相当于我们经常使用的临时变量;
- 特殊寄存器va、fs:分别针对于顶点寄存器和片段寄存器有不同的意义,va是真正存放顶点信息属性的寄存器,fs真正存放纹理信息的寄存器;
- 常量寄存器vc、fc:分别是针对顶点寄存器和片段寄存器:vc是主要保存位置变化等常量、fc主要保存颜色数据等常量,其实往往我们也就只存放颜色信息;
- V寄存器:用于顶点寄存器与片段寄存器之间的交互。
3. 每种寄存器都有自己的数量,总的可用寄存器为198个,每个寄存器有4位
- op、oc:只有一个 不存在 op1 op2...oc0 用法 ;
- v、vt、va、ft、fs:有8个 vt0~vt7 fs0~fs7;
- vc 有128个:vc0~vc127 ;
- fc 有28个:fc0~fc27;
4. 寄存器的传值:寄存器俺按传值分类可以分为两类:不允许传值和允许传值的。
- 不允许传值的有op、oc、vt、ft、v四个寄存器。因为op、oc是用于输出的,只能在寄存器作为输出结果;vt、ft为临时的也只能在寄存器内部使用;v只是将顶点的信息方便的传递给片段寄存器,不允许传入值。
- 允许传值的
特殊寄存器:va传入顶点的属性,方式是:context3D.setVertexBufferAt(2,....);将信息传给顶点特殊寄存器va2;
fs传入纹理信息,方式是:context3D.setTextureAt(1,.....) 将纹理信息传给片段特殊寄存器fs1
常量寄存器vc、fc:有三种方式:context3D.setProgramConstantsFromByteArray()
context3D.setProgramConstantsFromMatrix()
context3D.setProgramConstantsFromVector()
这3个的方法的第一个参数均为type,表示这个常量是传给所有的顶点着色器呢还是所有的片段着色器 Context3DProgramType.VERTEX 顶
点Context3DProgramType.FRAGMENT 片段。
5.常用的操作码:
- mov 赋值 mov v0,va1 把va1的值赋给v0
- add 加法 add op va1,va2
- sub 减法
- mul乘法
- div 除法
- tex材质
- 更多的操作码的使用可以参照百度百科对AGAL操作码,一半的我们用这几个就其实已经够了。
一个关于AGAL使用的代码如下:
/**创建一个简单的着色器*/ private function initShader():void{ //创建顶点着色器 var vertaxShader:AGALMiniAssembler = new AGALMiniAssembler(); vertaxShader.assemble(Context3DProgramType.VERTEX, "m44 op,va0,vc0\n"+ //让第0个va寄存器和第0个vc寄存器进行m44运算(4*4矩阵乘法) "mov v0,va1\n" //把uv交给va1 ); //顶点着色器,每个顶点都会执行一次,也就是说,在每次执行时,va0就是当前正在处理的这个顶点的位置 //创建片段着色器 var fragmentShader:AGALMiniAssembler = new AGALMiniAssembler(); fragmentShader.assemble(Context3DProgramType.FRAGMENT, "tex oc,v0,fs0<2d,miplinear,repeat>\n"//把纹理交给fs0 结合 uv信息v1 进行采样运算 tex,获得最终颜色 ); //片段着色器,每个像素点都执行一次 //合并为一个着色器提交给显卡 shaderProgram = context3D.createProgram(); shaderProgram.upload(vertaxShader.agalcode,fragmentShader.agalcode); }
至此,比本上就已经了解了AGAL的使用了,下来要很炫的效果就看自己对这些操作码的使用!