1.The OpCode

This is what AGAL looks like:

//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

Doesn’t it look like hieroglyphics? What’s the key to access it?
The problem is that AGAL is very little documented at this stage. Let me try to cast some light on this mysterious shading language.
Every line of the shader is a command, specified by a 3 character string called “opcode”.
The syntax of an AGAL code line is the following:
<opcode> <destination> <source 1> <source 2 or sampler>
This is the key. Keep this syntax in mind and AGAL will suddenly stop looking like an unreadable blob.
Following the opcode, depending on the command there can also be a destination, and one or two sources. The destination and the sources are “registers”: small memory areas in the GPU for use by shaders (more on registers below).
AGAL features about 30 different opcodes. The full list of available opcodes can be found in the Molehill documentation. Here are some of the most common opcodes.
mov move data from source1 to destination, component-wise
add destination = source1 + source2, component-wise
sub destination = source1 – source2, component-wise
mul destination = source1 * source2, component-wise
div destination = source1 / source2, component-wise
dp3 dot product (3 components) between source1 and source2
dp4 dot product (4 components) between source1 and source2
m44 multiplication between 4 components vector in source1 and 4×4 matrix in source2
tex texture sample. Load from texture at source2 at coordinates source1.

2.AGAL Registers

Registers are small memory areas in the GPU that AGAL programs (shaders) can use during their execution. Registers are used both for the sources and for the destination of AGAL commands.
You can also pass parameters to your shaders through these registers.
Each register is 128 bits wide, meaning it contains 4 floating point values. Each of these values is called a “component” of the register.
Register components can be accessed both with through the “coordinate” accessors (xyzw), and through the color accessors (rgba).
So, the first component of a register, can be accessed both with:
<register name>.x
and with:
<register name>.r
Some of the opcodes above, like “add”, perform their operations “component wise”. This means that the addition operation is performed component by component.
These are six types of registers available.
1. Attribute Registers

These registers reference to the input VertexBuffer of the vertex shader. Therefore they are only available in vertex shaders.
In order to assign a VertexBuffer to a specific attribute register, use the function Context3D:setVertexBufferAt(), with the proper index.
Then from the shader, access the attribute register with the syntax: va<n>, where <n> is the index number of the attribute register.
There are a total of 8 attribute registers available to vertex shaders.
2. Constant Registers

These registers serve the purpose of passing parameters from Actionscript to the shaders. This is done through the Context3D::setProgramConstants() family of functions.
These registers are accessed from the shader with the syntax: vc<n>, for vertex shaders, and fc<n> for pixel shaders, where <n> is the index number of the constant register.
There are 128 constant registers available to vertex shaders, and 28 constant registers for pixel shaders.
3. Temporary Registers

These registers are available to shaders, that can use them for temporary calculations.
They are accessed with the syntax vt<n> (vertex) and ft<n> (pixel) where <n> is the register number.
There are 8 of these available for vertex shaders, and 8 for pixel shaders.
4. Output Registers

The Output Registers are where vertex and pixel shaders store the output of their calculation. For vertex shaders this output is a clip space position of the vertex. For pixel shaders it is the color of the pixel.
These registers are accessed with the syntax op, for vertex shaders, and oc, for pixel shaders.
There is obviously only one output register for vertex and for pixel shaders.
5. Varying Registers

These registers are used to pass data from vertex shaders to pixel shaders. The data that is passed gets properly interpolated by the GPU, so that the pixel shader receives the correct value for the pixel that is being processed.
Typical data that gets passed in this way is the vertex color, or the UV coordinates for texturing.
These registers can be accessed with the syntax v<n>, where <n> is the register number.
There are 8 varying registers available.
6. Texture Samplers

The texture sampler register are used to pick color values from textures, based on UV coordinates.
The texture to be used is specified through Actionscript with the call Context3D::setTextureAt().
The syntax for using texture samples is: fs<n> <flags>, where <n> is the sampler index, and <flags> is a set of one or more flags that specifies how the sampling should be made.
<flags> is a comma separated set of strings, that defines:
texture dimension. Can be: 2d, 3d, cube
mip mapping. Can be: nomip, mipnone, mipnearest, mipnone
texture filtering. Can be: nearest, linear
texture repeat. Can be: repeat, wrap, clamp.
So, for example, a standard 2d texture without mip mapping, and linear filtering could be sampled into temporary register ft1, with the following line:
“tex ft1, v0, fs0 <2d,linear,nomip> “
where the varying register v0 would hold the interpolated texture UVs.

3.Basic Parts Of Molehill:

3.1.Stage3D

Stage3D is the part that sits in-between Flash and all the GPU goodness. Stage3D does not sit in the display list (you cannot do a addChild on a Stage3D object). Stage3D just exists in the same way that stage just exists. Stage3D sits behind all your regular flash content but in front for the new StageVideo.
3.2.Context3D

A Stage3D will contain a Context3D. Think of it this way... It’s almost the same as Bitmap contains BitmapData. You do not draw to Bitmap in the same way as you do not render stuff in Stage3D. All the work is done with BitmapData the same as Context3D
3.3.VertextBuffer3D

Context3D will contain VertexBuffer3D objects. Think of VertexBuffer3D as being “instructions” on what to draw and what it should look like. VertexBuffer3D will contain a Vector.<Number> (array of type Number) that will define vertex position and colour for each vertex. (more on that in a bit)
3.4.IndexBuffer3D

The IndexBuffer3D just like the VertexBuffer3D will contain a Vector. But instead of a Vector.<Number> it contains a Vector.<uint> which defines triangles in VertexBuffer3D. Think of it this way... VertexBuffer3D will contain a bunch of positions but IndexBuffer3D will determine what order those positions should be drawn. As a real world example VertexBuffer3D defines cities on a map then IndexBuffer3D will define what order to visit those cities.
3.5.Program3D

Program3D is a “program” that will run through the data in your VertexBuffer3D and “modify it”. Program3D contains two shaders (smaller programs) that will modify the position of every vertex and figure out what every pixel within a triangle should look like. The two smaller shaders or “programs” are called VertexShader and FragmentShader.
3.6.AGAL

AGAL is a very low level language. It’s used to write your VertexShaders and FragmentShaders. It’s the heart of MoleHill.
3.7.VertexShader

The VertexShader is a small program written in AGAL that will modify the Vertex positions within a triangle. For instance if you wanted to scale, rotate, or move your triangle you would use the VertexShader to do this.
3.8.FragmentShader

The FragmentShader is another small program written in AGAL that will modify the pixels in your triangle. For instance if you want to tint your entire triangle red you would write a small FragmentShader to do that
3.9.Quick diagram on how all the parts interrelate:

4. Using Molehill

When you use Molehill there are really two parts to your program:
* Setup
* Render
4.1.Things we want to do during Setup:

1. Get a Context3D instance from Stage3D
2. Setup the Context3D
3. Create an VertexBuffer
4. Create an IndexBuffer
5. Upload Initial Vertex Data to the VertexBuffer
6. Upload Initial Index Data to the IndexBuffer
7. “Compile” a VertexShader
8. “Compile” a FragmentShader
9. Create a Program3D which will use the above shaders
10. Add a ENTER_FRAME loop which will send data to the GPU
I know that’s a lot of stuff just to get this sucker setup but it’s not as bad as it sounds. Setup is WAY more complicated in my mind then the actual rendering.
4.2.Things we want to do during Render (ENTER_FRAME):

1. Clear the Context3D
2. Set the Program3D that will be using
3. Send the Vertex Buffer to Context3D
4. Setup data for you your shaders (variables)
5. Draw some triangles
6. Update the screen with your drawn triangles

5.Now let’s dig into source code.

The setup part described above is done in the function “onGotContext”. This is because in order to get the Context3D we have to request it and when it’s available Flash will send it to us.
The render part happens in the ENTER_FRAME function listener “onRenderLoop”.
Enjoy... I tried to write as many comments as possible in the code so you can follow along. I should note that this source code is based on Thibault Imbert’s blog post and this video.

import com.adobe.utils.*;

import flash.display.Bitmap;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.display3D.*;
import flash.display3D.textures.Texture;
import flash.events.*;
import flash.events.Event;
import flash.geom.Matrix3D;
import flash.geom.Rectangle;
import flash.geom.Vector3D;
import flash.utils.Timer;
import flash.utils.getTimer; [SWF(width="800", height="600", frameRate="60", backgroundColor="#FFFFFF")]
public class AgalSample extends Sprite
{
[Embed( source = "RockSmooth.jpg" )]
protected const TextureBitmap:Class; protected var context3D:Context3D;
protected var vertexbuffer:VertexBuffer3D;
protected var indexBuffer:IndexBuffer3D;
protected var program:Program3D;
protected var texture:Texture; public function AgalSample()
{
stage.stage3Ds[0].addEventListener( Event.CONTEXT3D_CREATE, initMolehill );
stage.stage3Ds[0].requestContext3D(); stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT; addEventListener(Event.ENTER_FRAME, onRender);
} protected function initMolehill(e:Event):void
{
context3D = stage.stage3Ds[0].context3D; context3D.configureBackBuffer(800, 600, 1, true); var vertices:Vector.<Number> = Vector.<Number>([
-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]); // 4 vertices, of 5 Numbers each
vertexbuffer = context3D.createVertexBuffer(4, 5);
// offset 0, 4 vertices
vertexbuffer.uploadFromVector(vertices, 0, 4); // total of 6 indices. 2 triangles by 3 vertices each
indexBuffer = context3D.createIndexBuffer(6); // offset 0, count 6
indexBuffer.uploadFromVector (Vector.<uint>([0, 1, 2, 2, 3, 0]), 0, 6); var bitmap:Bitmap = new TextureBitmap(); texture=context3D.createTexture(bitmap.bitmapData.width, bitmap.bitmapData.height, Context3DTextureFormat.BGRA, false);
texture.uploadFromBitmapData(bitmap.bitmapData); 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"
); program = context3D.createProgram();
program.upload(vertexShaderAssembler.agalcode, fragmentShaderAssembler.agalcode); } protected function onRender(e:Event):void
{
if ( !context3D )
return; 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); var m:Matrix3D = new Matrix3D();
m.appendRotation( getTimer()/50, Vector3D.Z_AXIS);
context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, m, true); context3D.drawTriangles(indexBuffer); context3D.present();
}
}

原文:http://labs.jam3.ca/2011/03/molehill-getting-started/

MoleHill Getting Started AGAL(转)的更多相关文章

  1. 初探Stage3D(二) 了解AGAL

    关于本文 本文并无打算事无巨细的介绍一遍AGAL,仅仅是对现有文档的一些理解及汇总,所以请先阅读相参考文档 AGAL概念 参考资料 http://www.adobe.com/devnet/flashp ...

  2. Stage3d AGAL GPU处理照片 旧照片效果 sepia || pixelbender

    如果看不到下边的flash,请更新flash player到最新版本. 利用AGAL实现旧照片效果,大家可以对照一下之前一篇文章,关于图像处理(pixelbender).硬件处理肯定会更快,但这里无法 ...

  3. Stage3d 由浅到深理解AGAL的管线vertex shader和fragment shader || 简易教程 学习心得 AGAL 非常非常好的入门文章

    Everyday Stage3D (一) Everyday Stage3D (二) Triangle Everyday Stage3D (三) AGAL的基本概念 Everyday Stage3D ( ...

  4. 新人补钙系列教程之:Molehill底层API中最重要的Context3D

    Context3D,是一个三维空间的处理环境,负责创建并处理三维对象的各个要素如顶点.片段.透视等等,并将处理的结果使用AGAL(Adobe图形汇编语言)上传给显卡进行运算,运算结果最终被回传给CPU ...

  5. stage3D基础三------什么是AGAL(转)

    原文链接 http://www.adobe.com/cn/devnet/flashplayer/articles/hello-triangle.html 在本文中,你将研究一个能够正常运行的基于Sta ...

  6. Shader与AGAL(From 7yue)

  7. (转) [it-ebooks]电子书列表

    [it-ebooks]电子书列表   [2014]: Learning Objective-C by Developing iPhone Games || Leverage Xcode and Obj ...

  8. 3D游戏中的画质与效率适配

      哪里来的需求? 众所周知,由于不同的设备配置不同.导致其CPU和GPU处理能力有高有低.同样的游戏想要在所有设备上运行流畅且画面精美,是不可能的.这就需要我们针对不同的设备能力进行画质调节,以保证 ...

  9. 基于Adobe Flash平台的3D页游技术剖析

    写在前面 从黑暗之光,佛本是道,大战神的有插件3D页游.再到如今的魔龙之戒. 足以证明,3D无插件正在引领页游技术的潮流. 目前,要做到3D引擎,有以下几个选择. 说到这里,我们发现.这些都不重要. ...

随机推荐

  1. 黑马程序员——OC语言 核心语法 (3)

    Java培训.Android培训.iOS培训..Net培训.期待与您交流! (以下内容是对黑马苹果入学视频的个人知识点总结) (一)分类Category 1) 基本用途 如何在不改变原来类模型的前提下 ...

  2. input、button、文字的对齐水平对齐

    input.button.文字的对齐~! 1.input文本框下移的方法:padding-top ,可以解决文本框向下移. 2.input文本框和button对齐可以给他们外面加table (例如,谷 ...

  3. RedHad中yum安装与使用

    yum的安装对于linux来说,是一个福音,至少安装软件来说,非常非常方便,以前使用rpm安装,那个各种依赖,哎,说多了都是泪,现在有这个yum就方便多了. 此处记录redhad的安装.其实我也是借鉴 ...

  4. block捕获自动变量和对象

    一.捕获自动变量值 首先看一个经典block面试题: int val = 10; void (^blk)(void) = ^{printf("val=%d\n",val);}; v ...

  5. 查看oracle当前session

      怎样查看oracle当前的连接数呢?只需要用下面的SQL语句查询一下就可以了. #查看当前不为空的连接select * from v$session where username is not n ...

  6. The differences between Java application and Java applet

    在Java语言中,能够独立运行的程序称为Java应用程序(Application).Java语言还有另外一种程序--Applet程序.Applet程序(也称Java小程序)是运行于各种网页文件中,用于 ...

  7. php建立MySQL数据表

    <?php $connect = mysql_connect("127.0.0.1","root",""); mysql_select ...

  8. Nginx 502 Bad Gateway 错误的原因及解决方法

    http://my.oschina.net/zhouyuan/blog/118708 刚才在调试程序的时候,居然服务器502错误,昨天晚上也发生了,好像我没有做非常规的操作. 然后网上寻找了下答案, ...

  9. 《统计推断(Statistical Inference)》读书笔记——第4章 统计分布族

    数据分析工作中最常和多维随机变量打交道,第四章介绍了多维随机变量的基本知识,其中核心概念是条件分布和条件概率.条件分布和条件概率可以抽象出条件期望的概念,在随机分析的研究中,理解随机积分和鞅理论和关键 ...

  10. jquery datatables双击,获取行号。

    function dbClickDatatables(rows) { $("#@(Perfix)tbData tbody tr").dblclick(function(e){ de ...