在本系列的part1中,我讨论了一些AGAL主要概念。
AGAL现在还是有点神秘…文档很少,但它确实很强大。
在flash发布之初,即使是释放出这种脚本语言全部的能力,它还是不尽如人意,这就是flash,它可以说是一个运行很慢的东西。但AGAL能运算到GPU有多快,它就有多快。
问题是,它是一个汇编语言。所以它很难掌握,而且也不能像使用我们熟悉的actionscript那样直观。
可能初一看起来,AGAL像一条条象形文字。希望这个问题在part1已经有所解决。如果你通过了,你应该知道有关的操作码和寄存器,并感觉更熟悉它。
但是试想一下,如果你正在处理外星文明的语言…有着不同的文化…你还缺少什么才能与他们沟通?
对…还缺少与他们沟通的门户…你的星际之门。
你的语言是ActionScript。他们的语言AGAL,星际之门正是MoleHill API。
欢迎来到跨星系编码!
着色器的Actionscript端编程
在Molehill中,所有的渲染都需要着色器来完成,没有着色器,就无法渲染。而Molehill API都是用来让着色器运行的,这说明AGAL与着色器在MoleHill中处于多么核心的位置。
在part1中的超简单着色器:
//vertex shader
m44 op, va0, vc0 // pos to clipspace
mov v0, va1 // copy uv
//pixel shader
tex ft1, v0, fs0 <2d,linear,nomip>
mov oc, ft1
现在我们希望从ActionScript运行它…。
第一件事情,你需要通过顶点集描述一个几何形。
假设你要显示一个由四个顶点组成的正方形。
var vertices:Vector. = Vector.([
-0.5,-0.5,0, 0, 0, // x, y, z, u, v
-0.5, 0.5, 0, 0, 1,
0.5, 0.5, 0, 1, 1,
0.5, -0.5, 0, 1, 0]);
每个顶点由X,Y,Z轴位置,和U,V纹理坐标构成。
这些顶点存储到一个VertexBuffer3D
// 4 vertices, of 5 Numbers each
var vertexbuffer:VertexBuffer3D = context3D.createVertexBuffer(4, 5);
通过context3D被上传到GPU。
vertexbuffer.uploadFromVector(vertices, 0, 4);
然后,您需要定义三角形,我们通过索引缓冲区来实现。
// total of 6 indices. 2 triangles by 3 vertices each
var indexbuffer:IndexBuffer3D = context3D.createIndexBuffer(6);
此索引缓冲区基本上定义了2个三角形。第一个是顶点0,1,2。第二个是顶点2,3和0。
跟顶点缓冲区一样,我们上传索引缓冲区到GPU之后,我们才可以使用它。
// offset 0, count 6
indexbuffer.uploadFromVector (Vector.<uint>([0, 1, 2, 2, 3, 0]), 0, 6);
您还需要一个可以发送到GPU的纹理。这仅仅是一个嵌入到你的SWF的jpg(或外部加载的图像):
var bitmap:Bitmap = new TextureBitmap();
var texture:Texture = context3D.createTexture(bitmap.bitmapData.width,
bitmap.bitmapData.height, Context3DTextureFormat.BGRA, false);
texture.uploadFromBitmapData(bitmap.bitmapData);
最终,你首先需要使用AGALMiniAssembler编译AGAL着色程序。
var vertexShaderAssembler : AGALMiniAssembler = new AGALMiniAssembler();
vertexShaderAssembler.assemble( Context3DProgramType.VERTEX,
"m44 op, va0, vc0\n" + // pos to clipspace
"mov v0, va1" // copy uv
);
var fragmentShaderAssembler : AGALMiniAssembler= new AGALMiniAssembler();
fragmentShaderAssembler.assemble( Context3DProgramType.FRAGMENT,
"tex ft1, v0, fs0 <2d,linear, nomip>;\n" +
"mov oc, ft1"
);
然后上传两个顶点和像素着色器程序到GPU:
var program:Program3D = context3D.createProgram();
program.upload( vertexShaderAssembler.agalcode, fragmentShaderAssembler.agalcode);
足够啦!我现在就想渲染!
ok,一切都已经上传并准备就绪,你现在可以渲染了…yay!
第一件事,清除你的视窗的一些背景颜色:
context3D.clear ( 1, 1, 1, 1 );
然后指定顶点缓冲,索引缓冲,纹理和着色程序
// vertex position to attribute register 0
context3D.setVertexBufferAt (0, vertexbuffer, 0, Context3DVertexBufferFormat.FLOAT_3);
// uv coordinates to attribute register 1
context3D.setVertexBufferAt(1, vertexbuffer, 3, Context3DVertexBufferFormat.FLOAT_2);
// assign texture to texture sampler 0
context3D.setTextureAt( 0, texture );
// assign shader program
context3D.setProgram( program );
请注意两个顶点缓冲流,顶点位置和UV坐标,如何分配给两个不同的属性寄存器。纹理被分配到一个特定的纹理采样。
然后,你需要传递您的转换矩阵给着色器。我不会做任何花哨的3D投影。只是一个基本的变换矩阵。
var m:Matrix3D = new Matrix3D();
m.appendRotation(getTimer()/50, Vector3D.Z_AXIS);
context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, m, true);
矩阵在这里获取存储到常量寄存器0,供顶点着色器使用。
要渲染只需调用drawTriangles,传参索引缓冲。
context3D.drawTriangles( indexBuffer);
你可以在帧上调用额外的drawTriangle,来绘制其它的几何形。在这些结束后,只需要执行present(),来实际渲染这帧。
context3D.present();
它真的运行了吗?
你自己看看吧,下面就是刚刚建好的应用示例。
这里是源代码:
在里下载这个简单的demo:下载
酷!现在,这下我可以写一个着色器了吧?
对,你可以了!这只是一个简单的demo,但它足以让您尝试不同的着色器,只要改变着色器代码,看看AGAL给你带来什么。
相关阅读第一部分:我叫AGAL,来自Adobe – Part1
翻译:xncat
转载注明来源:http://www.wefdc.com/?p=198
英文原文:http://iflash3d.com/shaders/my-name-is-agal-i-come-from-adobe-2/