1、AGAL: Adobe Graphics Assembly Language
在3D图形中,术语shader被普遍使用,通常我们把vertex program称为顶点着色器, fragment program称为像素着色器或片段着色器。Vertex and fragment
programs 执行效率非常快,每秒执百万次,是因为它们运行于显卡上(GPU),
vertex program 会把模型上的每个顶点都执行一次,fragment program 则是每个
像素都执行一次。
2、AGAL是什么样子的
<opcode> <destination> <source 1> <source 2>
<opcode>操作码
<destination>目标,计算结果存放处
<source1><source2>需要计算的源对像
AGAL只有大约30个不同的操作码,下面是几个常用的命令:
mov (copies data from source1 to destination)
add (destination = source1 plus source2)
sub (destination = source1 minus source2)
mul (destination = source1 multiplied by source2)
div (destination = source1 divided by source2)
一般加减乘除可以这样 add source1 source2 意为source1 += source2
3、什么是寄存器
前面的例子中的destination和source称为寄存器,你可以把它当成是用来存放数据的变
量。
在AGAL,寄存器是有限的,如果你创建的着色器较多,寄存器将会被用完,所以必须要
重复使用有限的寄存器。
寄存器都是128位的,可以存放4个32位浮点数(Number类型)。
不同的寄存器负责不同的工作,例如:va寄存器有8个,v0,v1,v2,v3,v4,v5,v6,v7.
mov v0,va1 就是把va1的值复制到v0,v0是8个varying寄存器中的一个。
4、什么是分量
每个寄存器都有4个值,叫分量,可以通过xyzw或rgba访问,例如:va1.x等同于va1.r,
都是访问寄存器的第一个分量。
顶点着色器的寄存器分量用xyzw访问,片段着色器的寄存器分量用rgba访问。
例如:so1 = vector3D (10,100,50,0)
so2 = vector3D (5,1,3,0)
add so1,so2
结果:so1 的值为(15,101,53,0),就是把so1与so2的xyzw对应相加,赋值给so1.
5、Vertex attribute registers: va0..va7
顶点属性寄存器
这些寄存器分配到VertexBuffer里的特定位置,它们只是顶点着色器的变量。当你要上传你
的模型数据时,可以包括xyz坐标
和其他的Number型数据,一般这些数据包括UV坐标,法线,rgb颜色和其他你想分配到每
个顶点的数据。
使用带适当索引的函数 Context3D:setVertexBufferAt(),可以把VertexBuffer分配到指
定的属性寄存器,例如,在字节数组中
前面的3个数是xyz值,访问属性寄存器语法,va<n>,n就是属性寄存器的索引号,那么
va0就指向每个顶点的位置xyz值。
在顶点着色器中,总共有8个属性寄存器,分别为va0,va1,va2,va3,va4,va5,va6,va7。
6、Constant registers: vc0..vc127 and fc0..fc27
常量寄存器
这些寄存器是由AS3的 Context3D::setProgramConstants方法把参数发送到着色器。
在顶点着色器中有128个常量寄存器
,用vc<n>访问,像素着色器中有28个常量寄存器,用fc<n>访问,n是常量寄存器的索引,
例如在设定灯光方向或雾的颜色等需要用到。
7、Temporary registers: vt0..vt7 and ft0..ft7
临时寄存器
顶点和像素着色器各有8个临时寄存器,以用于存储临时计算结果,顶点访问vt0~vt7,像素
访问ft0~ft7。
8、Output registers: op and oc
输出寄存器
op for output position and oc for output color
存放顶点和像素着色器的最终计算结果,顶点着色器输出的是顶点的空间坐标位置,像素
着色器输出的是像素的颜色,它们都只有一个输出寄存器。
9、Varying registers: v0..v7
变量寄存器
这些寄存器是把数据从顶点着色器传递到像素着色器,这些数据会经过GPU插值,因此,
像素着色器收到的是被处理过的正确的值。典型的数据包括顶点的颜色与纹理的UV坐标,
可通过v<n>访问,n是索引,总共有8个变量寄存器。
例如:在顶点着色器中,通过摄像机与雾的距离计算顶点的颜色,把这些数据传递给
像素着色器,像素着色器会把这些数据插值处理,以使这些颜色能够平滑过渡。
10、Texture samplers: fs0..fs7
纹理采样器
这8个纹理采样寄存器是基于UV坐标从纹理中拾取颜色值的,有自己的设置规则,仅用于像
素着色器,通过 Context3D::setTextureAt()来指定纹理。
例如一个标准的2D贴图 没有 mip mapping 加入了线性滤镜 linear filtering ,会取样到
临时寄存器 ft1,变量寄存器v0是存放经过插值的纹理UV坐标:
tex ft1, v0, fs0 <2d,linear,nomip>
使用语法:ft<n> <flags>,n是索引值,<flags>则是通过字符串来设置如何取样。
纹理尺寸:2d, 3d, or cube
2d就不用说了,3d是带深度,cube则是由6矩形位图编码成一组,通常用于反光
(reflections,不知道怎么翻译),每张图片都有特定的方向,类似一个盒子的内部的面一样。
mip mapping: nomip, mipnone, mipnearest, or miplinear
使用mip maps时,stage3D会把纹理进行平滑插值,把位图变成2的n次方大小的多张
图组成的金字塔状,用于复杂的渲染。
详细可以百度或谷歌 mipmap。
纹理滤镜:nearest or linear
使用 nearest ,当你近距离观看时,stage3D不会对其进行平滑插值,以生成4角形
的纹理;
使用 linear ,当对其进行缩放时,stage3D会对其进行模糊和平滑边界。
纹理重复:repeat, wrap, or clamp
使用 repeat ,可以使纹理平铺;
使用 clamp , 当你不想使用纹理平铺,并且在运行中遇到边缘像素变成背面边缘的
颜色的问题时,(通常在透明粒子和在渲染3d中的位图字体时会发生),会强制
stage3D不对相邻的边缘像素进行模糊。
11、A basic AGAL shader example
(1)The vertex program
每个顶点运行一次
Here is your first taste of AGAL: a simple vertex program.
// the simplest possible vertex program
m44 op, va0, vc0 // pos to clipspace
mov v0, va1 // copy uv
第一行代码,是一个4x4矩阵乘法,由有4个分量的Vector3D va0乘以一个 4x4 Matrix3D
vc0(vc0定义了顶点位置与摄像机的
关系,由 setProgramConstantsFromMatrix 方法设置),计算结果存放到op。 第二行
代码,是把存放UV坐标的va1 复制到v0
(2)The fragment program
每个像素运行一次
This is an example of a very simple fragment program:
// a simple fragment program
tex ft1, v0, fs0 <2d,linear,nomip>
mov oc, ft1
第一行代码,操作码 tex 执行纹理查找, fs0由 setTextureAt()设置,v0存放了UV坐标,
用于查找纹理中最近的像素,并经过线性插值,不使用mipmaps 来得到像素的r,g,b,a颜色,
存放在临时寄存器ft1中。
第二行代码,就是把ft1 复制到 oc 以输出。
12、Compiling the AGAL source code
在写的a vertex program and a fragment program 时需要用到adobe的类
AGALMiniAssembler 来把AGAL编译成字节码上传到显卡,接下来都是说代码的,省略,
直接在详细代码中说好了。
13、Creating a shader demo
都是比较基础的英文,就不翻译了
复制代码
在3D图形中,术语shader被普遍使用,通常我们把vertex program称为顶点着色器, fragment program称为像素着色器或片段着色器。Vertex and fragment
programs 执行效率非常快,每秒执百万次,是因为它们运行于显卡上(GPU),
vertex program 会把模型上的每个顶点都执行一次,fragment program 则是每个
像素都执行一次。
2、AGAL是什么样子的
<opcode> <destination> <source 1> <source 2>
<opcode>操作码
<destination>目标,计算结果存放处
<source1><source2>需要计算的源对像
AGAL只有大约30个不同的操作码,下面是几个常用的命令:
mov (copies data from source1 to destination)
add (destination = source1 plus source2)
sub (destination = source1 minus source2)
mul (destination = source1 multiplied by source2)
div (destination = source1 divided by source2)
一般加减乘除可以这样 add source1 source2 意为source1 += source2
3、什么是寄存器
前面的例子中的destination和source称为寄存器,你可以把它当成是用来存放数据的变
量。
在AGAL,寄存器是有限的,如果你创建的着色器较多,寄存器将会被用完,所以必须要
重复使用有限的寄存器。
寄存器都是128位的,可以存放4个32位浮点数(Number类型)。
不同的寄存器负责不同的工作,例如:va寄存器有8个,v0,v1,v2,v3,v4,v5,v6,v7.
mov v0,va1 就是把va1的值复制到v0,v0是8个varying寄存器中的一个。
4、什么是分量
每个寄存器都有4个值,叫分量,可以通过xyzw或rgba访问,例如:va1.x等同于va1.r,
都是访问寄存器的第一个分量。
顶点着色器的寄存器分量用xyzw访问,片段着色器的寄存器分量用rgba访问。
例如:so1 = vector3D (10,100,50,0)
so2 = vector3D (5,1,3,0)
add so1,so2
结果:so1 的值为(15,101,53,0),就是把so1与so2的xyzw对应相加,赋值给so1.
5、Vertex attribute registers: va0..va7
顶点属性寄存器
这些寄存器分配到VertexBuffer里的特定位置,它们只是顶点着色器的变量。当你要上传你
的模型数据时,可以包括xyz坐标
和其他的Number型数据,一般这些数据包括UV坐标,法线,rgb颜色和其他你想分配到每
个顶点的数据。
使用带适当索引的函数 Context3D:setVertexBufferAt(),可以把VertexBuffer分配到指
定的属性寄存器,例如,在字节数组中
前面的3个数是xyz值,访问属性寄存器语法,va<n>,n就是属性寄存器的索引号,那么
va0就指向每个顶点的位置xyz值。
在顶点着色器中,总共有8个属性寄存器,分别为va0,va1,va2,va3,va4,va5,va6,va7。
6、Constant registers: vc0..vc127 and fc0..fc27
常量寄存器
这些寄存器是由AS3的 Context3D::setProgramConstants方法把参数发送到着色器。
在顶点着色器中有128个常量寄存器
,用vc<n>访问,像素着色器中有28个常量寄存器,用fc<n>访问,n是常量寄存器的索引,
例如在设定灯光方向或雾的颜色等需要用到。
7、Temporary registers: vt0..vt7 and ft0..ft7
临时寄存器
顶点和像素着色器各有8个临时寄存器,以用于存储临时计算结果,顶点访问vt0~vt7,像素
访问ft0~ft7。
8、Output registers: op and oc
输出寄存器
op for output position and oc for output color
存放顶点和像素着色器的最终计算结果,顶点着色器输出的是顶点的空间坐标位置,像素
着色器输出的是像素的颜色,它们都只有一个输出寄存器。
9、Varying registers: v0..v7
变量寄存器
这些寄存器是把数据从顶点着色器传递到像素着色器,这些数据会经过GPU插值,因此,
像素着色器收到的是被处理过的正确的值。典型的数据包括顶点的颜色与纹理的UV坐标,
可通过v<n>访问,n是索引,总共有8个变量寄存器。
例如:在顶点着色器中,通过摄像机与雾的距离计算顶点的颜色,把这些数据传递给
像素着色器,像素着色器会把这些数据插值处理,以使这些颜色能够平滑过渡。
10、Texture samplers: fs0..fs7
纹理采样器
这8个纹理采样寄存器是基于UV坐标从纹理中拾取颜色值的,有自己的设置规则,仅用于像
素着色器,通过 Context3D::setTextureAt()来指定纹理。
例如一个标准的2D贴图 没有 mip mapping 加入了线性滤镜 linear filtering ,会取样到
临时寄存器 ft1,变量寄存器v0是存放经过插值的纹理UV坐标:
tex ft1, v0, fs0 <2d,linear,nomip>
使用语法:ft<n> <flags>,n是索引值,<flags>则是通过字符串来设置如何取样。
纹理尺寸:2d, 3d, or cube
2d就不用说了,3d是带深度,cube则是由6矩形位图编码成一组,通常用于反光
(reflections,不知道怎么翻译),每张图片都有特定的方向,类似一个盒子的内部的面一样。
mip mapping: nomip, mipnone, mipnearest, or miplinear
使用mip maps时,stage3D会把纹理进行平滑插值,把位图变成2的n次方大小的多张
图组成的金字塔状,用于复杂的渲染。
详细可以百度或谷歌 mipmap。
纹理滤镜:nearest or linear
使用 nearest ,当你近距离观看时,stage3D不会对其进行平滑插值,以生成4角形
的纹理;
使用 linear ,当对其进行缩放时,stage3D会对其进行模糊和平滑边界。
纹理重复:repeat, wrap, or clamp
使用 repeat ,可以使纹理平铺;
使用 clamp , 当你不想使用纹理平铺,并且在运行中遇到边缘像素变成背面边缘的
颜色的问题时,(通常在透明粒子和在渲染3d中的位图字体时会发生),会强制
stage3D不对相邻的边缘像素进行模糊。
11、A basic AGAL shader example
(1)The vertex program
每个顶点运行一次
Here is your first taste of AGAL: a simple vertex program.
// the simplest possible vertex program
m44 op, va0, vc0 // pos to clipspace
mov v0, va1 // copy uv
第一行代码,是一个4x4矩阵乘法,由有4个分量的Vector3D va0乘以一个 4x4 Matrix3D
vc0(vc0定义了顶点位置与摄像机的
关系,由 setProgramConstantsFromMatrix 方法设置),计算结果存放到op。 第二行
代码,是把存放UV坐标的va1 复制到v0
(2)The fragment program
每个像素运行一次
This is an example of a very simple fragment program:
// a simple fragment program
tex ft1, v0, fs0 <2d,linear,nomip>
mov oc, ft1
第一行代码,操作码 tex 执行纹理查找, fs0由 setTextureAt()设置,v0存放了UV坐标,
用于查找纹理中最近的像素,并经过线性插值,不使用mipmaps 来得到像素的r,g,b,a颜色,
存放在临时寄存器ft1中。
第二行代码,就是把ft1 复制到 oc 以输出。
12、Compiling the AGAL source code
在写的a vertex program and a fragment program 时需要用到adobe的类
AGALMiniAssembler 来把AGAL编译成字节码上传到显卡,接下来都是说代码的,省略,
直接在详细代码中说好了。
13、Creating a shader demo
都是比较基础的英文,就不翻译了
- package
- {
- import com.adobe.utils.AGALMiniAssembler;
- import com.adobe.utils.PerspectiveMatrix3D;
- import flash.display.Bitmap;
- import flash.display.BitmapData;
- import flash.display.Sprite;
- import flash.display.Stage3D;
- import flash.display.StageAlign;
- import flash.display.StageScaleMode;
- import flash.display3D.Context3D;
- import flash.display3D.Context3DProgramType;
- import flash.display3D.Context3DTextureFormat;
- import flash.display3D.Context3DVertexBufferFormat;
- import flash.display3D.IndexBuffer3D;
- import flash.display3D.Program3D;
- import flash.display3D.textures.Texture;
- import flash.display3D.VertexBuffer3D;
- import flash.events.Event;
- import flash.geom.Matrix;
- import flash.geom.Matrix3D;
- import flash.geom.Vector3D;
- import flash.text.TextField;
- import flash.text.TextFieldAutoSize;
- import flash.text.TextFormat;
- import flash.utils.getTimer;
-
- /**
- * ...
- * @author lanphone
- */
- [SWF(width="640", height="480", frameRate="60")]
- public class Main extends Sprite
- {
- //用于显示fps
- private var fpsLast:uint = getTimer();
- private var fpsTicks:uint = 0;
- private var fpsTf:TextField;
-
- private const swfWidth:int = 640;
- private const swfHeight:int = 480;
- private const textureSize:int = 512;
-
- private var context3D:Context3D;
- //编译shader用于渲染
- private var shaderProgram1:Program3D;
- private var shaderProgram2:Program3D;
- private var shaderProgram3:Program3D;
- private var shaderProgram4:Program3D;
- //顶点缓冲
- private var vertexBuffer:VertexBuffer3D;
- //索引缓冲
- private var indexBuffer:IndexBuffer3D;
- //顶点数据
- private var meshVertexData:Vector.<Number>;
- //索引数据
- private var meshIndexData:Vector.<uint>;
- //影响顶点位置与摄像机角度的矩阵
- private var projectionmatrix:PerspectiveMatrix3D = new PerspectiveMatrix3D();
- private var modelmatrix:Matrix3D = new Matrix3D();
- private var viewmatrix:Matrix3D = new Matrix3D();
- private var modelViewmatrix:Matrix3D = new Matrix3D();
- //计数器
- private var t:Number = 0;
- private var looptemp:int = 0;
-
- [Embed(source = "bit.jpg")] private const myTextureBitmap:Class;
- private var myTextureData:Bitmap = new myTextureBitmap();
- private var myTexture:Texture;
-
-
- public function Main():void
- {
- if (stage) init();
- else addEventListener(Event.ADDED_TO_STAGE, init);
- }
-
- private function init(e:Event = null):void
- {
- removeEventListener(Event.ADDED_TO_STAGE, init);
- stage.scaleMode = StageScaleMode.NO_SCALE;
- stage.align = StageAlign.TOP_LEFT;
- initGUI();
- stage.stage3Ds[0].addEventListener(Event.CONTEXT3D_CREATE, onContext3DCreate);
- stage.stage3Ds[0].requestContext3D();
- }
-
- private function initGUI():void
- {
- // a text format descriptor used by all gui labels
- var myFormat:TextFormat = new TextFormat();
- myFormat.color = 0xFFFFFF;
- myFormat.size = 13;
- // create an FPSCounter that displays the framerate on screen
- fpsTf = new TextField();
- fpsTf.x = 0;
- fpsTf.y = 0;
- fpsTf.selectable = false;
- fpsTf.autoSize = TextFieldAutoSize.LEFT;
- fpsTf.defaultTextFormat = myFormat;
- fpsTf.text = "Initializing Stage3d...";
- addChild(fpsTf);
- // add some labels to describe each shader
- var label1:TextField = new TextField();
- label1.x = 100;
- label1.y = 180;
- label1.selectable = false;
- label1.autoSize = TextFieldAutoSize.LEFT;
- label1.defaultTextFormat = myFormat;
- label1.text = "Shader 1: Textured";
- addChild(label1);
-
- var label2:TextField = new TextField();
- label2.x = 400;
- label2.y = 180;
-
- label2.selectable = false;
- label2.autoSize = TextFieldAutoSize.LEFT;
- label2.defaultTextFormat = myFormat;
- label2.text = "Shader 2: Vertex RGB";
- addChild(label2);
-
- var label3:TextField = new TextField();
- label3.x = 80;
- label3.y = 440;
- label3.selectable = false;
- label3.autoSize = TextFieldAutoSize.LEFT;
- label3.defaultTextFormat = myFormat;
- label3.text = "Shader 3: Vertex RGB + Textured";
- addChild(label3);
-
- var label4:TextField = new TextField();
- label4.x = 340;
- label4.y = 440;
- label4.selectable = false;
- label4.autoSize = TextFieldAutoSize.LEFT;
- label4.defaultTextFormat = myFormat;
- label4.text = "Shader 4: Textured + setProgramConstants";
- addChild(label4);
- }
-
- private function onContext3DCreate(event:Event):void
- {
- // Remove existing frame handler. Note that a context
- // loss can occur at any time which will force you
- // to recreate all objects we create here.
- // A context loss occurs for instance if you hit
- // CTRL-ALT-DELETE on Windows.
- // It takes a while before a new context is available
- // hence removing the enterFrame handler is important!
- removeEventListener(Event.ENTER_FRAME,enterFrame);
-
- // Obtain the current context
- var t:Stage3D = event.target as Stage3D;
- context3D = t.context3D;
- if (context3D == null)
- {
- // Currently no 3d context is available (error!)
- return;
- }
- // Disabling error checking will drastically improve performance.
- // If set to true, Flash sends helpful error messages regarding
- // AGAL compilation errors, uninitialized program constants, etc.
- context3D.enableErrorChecking = true;
- // Initialize our mesh data
- initData();
- // The 3d back buffer size is in pixels
- context3D.configureBackBuffer(swfWidth, swfHeight, 0, true);
- // assemble all the shaders we need
- initShaders();
- // upload the mesh indexes
- indexBuffer = context3D.createIndexBuffer(meshIndexData.length);
- indexBuffer.uploadFromVector(meshIndexData, 0, meshIndexData.length);
- // upload the mesh vertex data
- // since our particular data is
- // x, y, z, u, v, nx, ny, nz, r, g, b, a
- // each vertex uses 12 array elements
- vertexBuffer = context3D.createVertexBuffer(meshVertexData.length / 12, 12);
- vertexBuffer.uploadFromVector(meshVertexData, 0, meshVertexData.length / 12);
- // Generate mipmaps
- myTexture = context3D.createTexture(textureSize, textureSize, Context3DTextureFormat.BGRA, false);
- uploadTextureWithMipmaps(myTexture, myTextureData.bitmapData);
- // create projection matrix for our 3D scene
- projectionmatrix.identity();
- // 45 degrees FOV, 640/480 aspect ratio, 0.01=near, 100=far
- projectionmatrix.perspectiveFieldOfViewRH(45, swfWidth / swfHeight, 0.01, 100);
- // create a matrix that defines the camera location
- viewmatrix.identity();
- // move the camera back a little so we can see the mesh
- viewmatrix.appendTranslation(0, 0, -10);
- // start animating
- addEventListener(Event.ENTER_FRAME,enterFrame);
- }
- public function uploadTextureWithMipmaps(dest:Texture, src:BitmapData):void
- {
- var ws:int = src.width;
- var hs:int = src.height;
- var level:int = 0;
- var tmp:BitmapData;
- var transform:Matrix = new Matrix();
-
- tmp = new BitmapData(src.width, src.height, true, 0x00000000);
-
- while ( ws >= 1 && hs >= 1 )
- {
- tmp.draw(src, transform, null, null, null, true);
- dest.uploadFromBitmapData(tmp, level);
- transform.scale(0.5, 0.5);
- level++;
- ws >>= 1;
- hs >>= 1;
- if (hs && ws)
- {
- tmp.dispose();
- tmp = new BitmapData(ws, hs, true, 0x00000000);
- }
- }
- tmp.dispose();
- }
- private function enterFrame(e:Event):void
- {
- // clear scene before rendering is mandatory
- context3D.clear(0, 0, 0);
- // rotate more next frame
- t += 2.0;
-
- // loop through each mesh we want to draw
- for (looptemp = 0; looptemp < 4; looptemp ++)
- {
- // clear the transformation matrix to 0,0,0
- modelmatrix.identity();
-
- // each mesh has a different texture,
- // shader, position and spin speed
- switch (looptemp)
- {
- case 0:
- context3D.setTextureAt(0, myTexture);
- context3D.setProgram ( shaderProgram1 );
- modelmatrix.appendRotation(t*0.7, Vector3D.Y_AXIS);
- modelmatrix.appendRotation(t*0.6, Vector3D.X_AXIS);
- modelmatrix.appendRotation(t*1.0, Vector3D.Y_AXIS);
- modelmatrix.appendTranslation(-3, 3, 0);
- break;
- case 1:
- context3D.setTextureAt(0, null);
- context3D.setProgram ( shaderProgram2 );
- modelmatrix.appendRotation(t*-0.2, Vector3D.Y_AXIS);
- modelmatrix.appendRotation(t*0.4, Vector3D.X_AXIS);
- modelmatrix.appendRotation(t*0.7, Vector3D.Y_AXIS);
- modelmatrix.appendTranslation(3, 3, 0);
- break;
- case 2:
- context3D.setTextureAt(0, myTexture);
- context3D.setProgram ( shaderProgram3 );
- modelmatrix.appendRotation(t*1.0, Vector3D.Y_AXIS);
- modelmatrix.appendRotation(t*-0.2, Vector3D.X_AXIS);
- modelmatrix.appendRotation(t*0.3, Vector3D.Y_AXIS);
- modelmatrix.appendTranslation(-3, -3, 0);
- break;
- case 3:
- context3D.setProgramConstantsFromVector(
- Context3DProgramType.FRAGMENT, 0, Vector.<Number>
- ([ 1, Math.abs(Math.cos(t/50)), 0, 1 ]) );
- context3D.setTextureAt(0, myTexture);
- context3D.setProgram ( shaderProgram4 );
- modelmatrix.appendRotation(t*0.3, Vector3D.Y_AXIS);
- modelmatrix.appendRotation(t*0.3, Vector3D.X_AXIS);
- modelmatrix.appendRotation(t*-0.3, Vector3D.Y_AXIS);
- modelmatrix.appendTranslation(3, -3, 0);
- break;
- }
- // clear the matrix and append new angles
- modelViewmatrix.identity();
- modelViewmatrix.append(modelmatrix);
- modelViewmatrix.append(viewmatrix);
- modelViewmatrix.append(projectionmatrix);
-
- // pass our matrix data to the shader program
- context3D.setProgramConstantsFromMatrix(
- Context3DProgramType.VERTEX,
- 0, modelViewmatrix, true );
- // associate the vertex data with current shader program
- // position
- context3D.setVertexBufferAt(0, vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_3);
- // tex coord
- context3D.setVertexBufferAt(1, vertexBuffer, 3, Context3DVertexBufferFormat.FLOAT_2);
- // vertex rgba
- context3D.setVertexBufferAt(2, vertexBuffer, 8, Context3DVertexBufferFormat.FLOAT_4);
- // finally draw the triangles
- context3D.drawTriangles(indexBuffer, 0, meshIndexData.length / 3);
- }
- // present/flip back buffer
- // now that all meshes have been drawn
- context3D.present();
- //update the fps display
- fpsTicks ++;
- var now:uint = getTimer();
- var delta:uint = now - fpsLast;
- if (delta >= 1000)
- {
- var fps:Number = fpsTicks / delta * 1000;
- fpsTf.text = fps.toFixed(1) + " fps";
- fpsTicks = 0;
- fpsLast = now;
- }
- }
-
- private function initShaders():void
- {
- // A simple vertex shader which does a 3D transformation
- // for simplicity, it is used by all four shaders
- var vertexShaderAssembler:AGALMiniAssembler = new AGALMiniAssembler();
- vertexShaderAssembler.assemble
- (
- Context3DProgramType.VERTEX,
- // 4x4 matrix multiply to get camera angle
- "m44 op, va0, vc0\n" +
- // tell fragment shader about XYZ
- "mov v0, va0\n" +
- // tell fragment shader about UV
- "mov v1, va1\n" +
- // tell fragment shader about RGBA
- "mov v2, va2\n"
- );
- // textured using UV coordinates
- var fragmentShaderAssembler1:AGALMiniAssembler = new AGALMiniAssembler();
- fragmentShaderAssembler1.assemble
- (
- Context3DProgramType.FRAGMENT,
- // grab the texture color from texture 0
- // and uv coordinates from varying register 1
- // and store the interpolated value in ft0
- "tex ft0, v1, fs0 <2d, repeat, miplinear>\n" +
- // move this value to the output color
- "mov oc, ft0\n"
- );
- // no texture, RGBA from the vertex buffer data
- var fragmentShaderAssembler2:AGALMiniAssembler = new AGALMiniAssembler();
- fragmentShaderAssembler2.assemble
- (
- Context3DProgramType.FRAGMENT,
- // grab the color from the v2 register
- // which was set in the vertex program
- "mov oc, v2\n"
- );
- // textured using UV coordinates AND colored by vertex RGB
- var fragmentShaderAssembler3:AGALMiniAssembler = new AGALMiniAssembler();
- fragmentShaderAssembler3.assemble
- (
- Context3DProgramType.FRAGMENT,
- // grab the texture color from texture 0
- // and uv coordinates from varying register 1
- "tex ft0, v1, fs0 <2d, repeat, miplinear>\n" +
- // multiply by the value stored in v2 (the vertex rgb)
- "mul ft1, v2, ft0\n" +
- // move this value to the output color
- "mov oc, ft1\n"
- );
- // textured using UV coordinates and
- // tinted using a fragment constant
- var fragmentShaderAssembler4:AGALMiniAssembler = new AGALMiniAssembler();
- fragmentShaderAssembler4.assemble
- (
- Context3DProgramType.FRAGMENT,
- // grab the texture color from texture 0
- // and uv coordinates from varying register 1
- "tex ft0, v1, fs0<2d, repeat, miplinear>\n" +
- // multiply by the value stored in fc0
- "mul ft1, fc0, ft0\n" +
- // move this value to the output color
- "mov oc, ft1\n"
- );
- // combine shaders into a program which we then upload to the GPU
- shaderProgram1 = context3D.createProgram();
- shaderProgram1.upload(vertexShaderAssembler.agalcode, fragmentShaderAssembler1.agalcode);
- shaderProgram2 = context3D.createProgram();
- shaderProgram2.upload(vertexShaderAssembler.agalcode, fragmentShaderAssembler2.agalcode);
- shaderProgram3 = context3D.createProgram();
- shaderProgram3.upload(vertexShaderAssembler.agalcode, fragmentShaderAssembler3.agalcode);
- shaderProgram4 = context3D.createProgram();
- shaderProgram4.upload(vertexShaderAssembler.agalcode, fragmentShaderAssembler4.agalcode);
- }
-
- private function initData():void
- {
- // Defines which vertex is used for each polygon
- // In this example a square is made from two triangles
- meshIndexData = Vector.<uint>
- ([
- 0, 1, 2, 0, 2, 3,
- ]);
-
- // Raw data used for each of the 4 vertexes
- // Position XYZ, texture coord UV, normal XYZ, vertex RGBA
- meshVertexData = Vector.<Number>
- ([
- //X, Y, Z, U, V, nX, nY, nZ, R, G, B, A
- -1, -1, 1, 0, 0, 0, 0, 1, 1.0,0.0,0.0,1.0,
- 1, -1, 1, 1, 0, 0, 0, 1, 0.0,1.0,0.0,1.0,
- 1, 1, 1, 1, 1, 0, 0, 1, 0.0,0.0,1.0,1.0,
- -1, 1, 1, 0, 1, 0, 0, 1, 1.0,1.0,1.0,1.0
- ]);
- }
-
- }
-
- }