MoleHill Getting Started AGAL(转)
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(转)的更多相关文章
- 初探Stage3D(二) 了解AGAL
关于本文 本文并无打算事无巨细的介绍一遍AGAL,仅仅是对现有文档的一些理解及汇总,所以请先阅读相参考文档 AGAL概念 参考资料 http://www.adobe.com/devnet/flashp ...
- Stage3d AGAL GPU处理照片 旧照片效果 sepia || pixelbender
如果看不到下边的flash,请更新flash player到最新版本. 利用AGAL实现旧照片效果,大家可以对照一下之前一篇文章,关于图像处理(pixelbender).硬件处理肯定会更快,但这里无法 ...
- Stage3d 由浅到深理解AGAL的管线vertex shader和fragment shader || 简易教程 学习心得 AGAL 非常非常好的入门文章
Everyday Stage3D (一) Everyday Stage3D (二) Triangle Everyday Stage3D (三) AGAL的基本概念 Everyday Stage3D ( ...
- 新人补钙系列教程之:Molehill底层API中最重要的Context3D
Context3D,是一个三维空间的处理环境,负责创建并处理三维对象的各个要素如顶点.片段.透视等等,并将处理的结果使用AGAL(Adobe图形汇编语言)上传给显卡进行运算,运算结果最终被回传给CPU ...
- stage3D基础三------什么是AGAL(转)
原文链接 http://www.adobe.com/cn/devnet/flashplayer/articles/hello-triangle.html 在本文中,你将研究一个能够正常运行的基于Sta ...
- Shader与AGAL(From 7yue)
- (转) [it-ebooks]电子书列表
[it-ebooks]电子书列表 [2014]: Learning Objective-C by Developing iPhone Games || Leverage Xcode and Obj ...
- 3D游戏中的画质与效率适配
哪里来的需求? 众所周知,由于不同的设备配置不同.导致其CPU和GPU处理能力有高有低.同样的游戏想要在所有设备上运行流畅且画面精美,是不可能的.这就需要我们针对不同的设备能力进行画质调节,以保证 ...
- 基于Adobe Flash平台的3D页游技术剖析
写在前面 从黑暗之光,佛本是道,大战神的有插件3D页游.再到如今的魔龙之戒. 足以证明,3D无插件正在引领页游技术的潮流. 目前,要做到3D引擎,有以下几个选择. 说到这里,我们发现.这些都不重要. ...
随机推荐
- C# 顺序高斯(Gauss)消去法计算一元多次方程组
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- git常用命令有用
http://www.cnblogs.com/cspku/articles/Git_cmds.html
- Android图片加载与缓存开源框架:Android Glide
<Android图片加载与缓存开源框架:Android Glide> Android Glide是一个开源的图片加载和缓存处理的第三方框架.和Android的Picasso库类似,个人感觉 ...
- centos lamp
一.安装 MySQL 首先来进行 MySQL 的安装.打开超级终端,输入: [root@localhost ~]# yum install mysql mysql-server 安装完毕,让 MySQ ...
- Redis持久化-数据丢失及解决(转载)
本文转载自 Redis持久化-数据丢失及解决 感谢原作者 Redis的数据回写机制 Redis的数据回写机制分同步和异步两种, 同步回写即SAVE命令,主进程直接向磁盘回写数据.在数据 ...
- BZOJ 1015 并查集+离线倒序
统计块个数写错了调了好久啊,BZOJ1696的弱化版本. #include <iostream> #include <cstring> #include <algorit ...
- dyld: Symbol not found: _OBJC_CLASS_$_NSURLSessionDataTask
dyld: Symbol not found: _OBJC_CLASS_$_NSURLSessionDataTask Referenced from: /var/mobile/Applicatio ...
- C语言共用体内存计算
其实union(共用体)的各个成员是以同一个地址开始存放的,每一个时刻只可以存储一个成员,这样就要求它在分配内存单元时候要满足两点: 1.一般而言,共用体类型实际占用存储空间为其最长的成员所占的存储空 ...
- CDN(内容分发网络)技术原理
1. 前言 Internet的高速发展,给人们的工作和生活带来了极大的便利,对Internet的服务品质和访问速度要求越来越高,虽然带宽不断增加, 用户数量也在不断增加,受Web服务器的负荷和传输距离 ...
- 【转载】C/C++中#ifdef和#endif的用法
转于 http://www.cnblogs.com/renyuan/archive/2013/05/22/3092362.html 今天笔试的时候遇到这个问题,整理一下! 一般情况下,源程序中所有的行 ...