`
cloud21
  • 浏览: 389887 次
  • 性别: Icon_minigender_2
  • 来自: 北京
社区版块
存档分类
最新评论

AGAL

    博客分类:
  • Game
阅读更多
AGAL Opcode 指令:
基本語法
[opcode] [destination] [source1] [source2 or sampler]
沒有使用到的欄位必須設為 0 (應該是指 bytecode)
mov move 分量移動 移動 source1 資料到 destination
add add 分量相加 destination = source1 + source2
sub subtract 分量相減 destination = source1 - source2
mul multiply 分量相乘 destination = source1 * source2
div divide 分量相除 destination = source1 / source2
rcp reciprocal 分量倒數 destination = 1 / source1
min minimum 分量最小值 destination = minimum(source1 , source2)
max maximum 分量最大值 destination = maximum(source1 , source2)
frc fractional 分量取小數 destination = source1 - (float) floor(source1)
sqt square 分量平方根 destination = sqrt(source1)
rsq recip. root 分量平方根倒數 destination = 1 / sqrt(source1)
pow power 分量指數 destination = pow(source1 , source2)
log logarithm 2 為底分量對數 destination = log_2(source1)
exp exponential 2 為底分量指數 destination = 2^source1
nrm normalize 分量標準化 destination = normalize(source1)
sin sine 分量正弦 destination = sin(source1)
cos cosine 分量餘弦 destination = cos(source1)

abs absolute 分量絕對值 destination = abs(source1)
neg negate 分量負值 destination = -source1
sat saturate 分量飽和值 destination = maximum(minimum(source1 , 1) , 0)



kil kill / discard (fragment shader only)
假如單一分量小於 0 便放棄繪圖
If single scalar source component is less than zero, fragment is discarded and not drawn to the frame buffer.
The destination register must be all 0.

tex texture sample (fragment shader only)
依據 source1 座標從 source2 材質取樣
destination = load from texture source2 at coordinates source1.
In this source2 must be in sampler format.

sge set-if-greater-equal
分量運算,假如 source1 大於等於 source2,目標為 1,否則目標為 0
destination = source1 >= source2 ? 1 : 0

slt set-if-less-than
分量運算,假如 source1 小於 source2,目標為 1,否則目標為 0
destination = source1 < source2 ? 1 : 0


crs cross product 向量外積
destination.x = source1.y * source2.z - source1.z * source2.y
destination.y = source1.z * source2.x - source1.x * source2.z
destination.z = source1.x * source2.y - source1.y * source2.x

dp3 dot product 向量內積
destination = source1.x * source2.x + source1.y * source2.y + source1.z * source2.z

dp4 dot product 向量內積
destination = source1.x * source2.x + source1.y * source2.y + source1.z * source2.z + source1.w * source2.w


m33 multiply 3x3 矩陣相乘
destination.x = (source1.x * source2[0].x) + (source1.y * source2[0].y) + (source1.z * source2[0].z)
destination.y = (source1.x * source2[1].x) + (source1.y * source2[1].y) + (source1.z * source2[1].z)
destination.z = (source1.x * source2[2].x) + (source1.y * source2[2].y) + (source1.z * source2[2].z)

m44 multiply 4x4 矩陣相乘
destination.x = (source1.x * source2[0].x) + (source1.y * source2[0].y) + (source1.z * source2[0].z) + (source1.w * source2[0].w)
destination.y = (source1.x * source2[1].x) + (source1.y * source2[1].y) + (source1.z * source2[1].z) + (source1.w * source2[1].w)
destination.z = (source1.x * source2[2].x) + (source1.y * source2[2].y) + (source1.z * source2[2].z) + (source1.w * source2[2].w)
destination.w = (source1.x * source2[3].x) + (source1.y * source2[3].y) + (source1.z * source2[3].z) + (source1.w * source2[3].w)

m34 multiply 3x4 矩陣相乘
destination.x = (source1.x * source2[0].x) + (source1.y * source2[0].y) + (source1.z * source2[0].z) + (source1.w * source2[0].w)
destination.y = (source1.x * source2[1].x) + (source1.y * source2[1].y) + (source1.z * source2[1].z) + (source1.w * source2[1].w)
destination.z = (source1.x * source2[2].x) + (source1.y * source2[2].y) + (source1.z * source2[2].z) + (source1.w * source2[2].w)
從 AGALMiniAssembler 裡面看到還有這些 opcode
ifz, inz, ife, ine, ifg, ifl, ieg, iel, els, eif, rep, erp, brk, sgn
不過實際測試發現在目前這版 Flash Player 尚未支援
Error: Error #3621: AGAL validation failed: Invalid opcode, ifg is not implemented in this version at token 2 of fragment program.
AGAL 基本語法:
vc0, va0 作 4x4 矩陣轉型後指定到輸出剪輯空間 (output clipspace)
m44 op, va0, vc
以上語法等於以下個別分量的單獨作內積
dp4 op.x, va0, vc0
dp4 op.y, va0, vc1
dp4 op.z, va0, vc2
dp4 op.w, va0, vc3
從 va1 複製到 v0 給 fragment shader 使用
mov v0, va1
等於
mov v0, va1.xyzw
注意 xyzw 順序
mov v0, va1.yxzw
實際上是等於
mov v0.x, va1.y
mov v0.y, va1.x
mov v0.z, va1.z
mov v0.w, va1.w
AS3中,编译AGAL指令须按照以下几个步骤:
1、创建AGALMiniAssembler类对象 (AGALMiniAssembler 是Adobe提供的用来将字符串格式的AGAL指令编译成二进制码的工具类),如:
var vertexShaderAssembler:AGALMiniAssembler = new AGALMiniAssembler();
var fragmentShaderAssembler:AGALMiniAssembler = new AGALMiniAssembler();
2、编译AGAL代码,如:
vertexShaderAssembler.assemble(Context3DProgramType.VERTEX,
"m44 op, va0, vc0\n" +
"mov v0, va0\n" +
"mov v1, va1\n" +
"mov v2, va2\n" );

  fragmentShaderAssembler.assemble(Context3DProgramType.FRAGMENT,
"tex ft0, v1, fs0<2d, repeat, miplinear>\n" +
"mov oc, ft0\n" );
3、创建Shader,如:
var shaderProgram:Program3D = _context3D.createProgram();
4、将编译后的AGAL代码上载给Shader ,如:
shaderProgram.upload(vertexShaderAssembler.agalcode, fragmentShaderAssembler.agalcode);

Stage3D AGAL中的顶点变换运算解析我们在Stage3D的底层API编写中,会经常遇到要处理以下情形:Vertex顶点在3D空间中的变换。这个行为会根据Render机制的不断刷新而形成3D物体在空间中整体坐标变换。

在编写Stage3D的应用中,最基础常见的AGAL OpCode是这样:

m44 op,va0,vc0

这个简单的OpCode构成了寄存器中的Vertex坐标的动态变换。那么接下来,就给出从头至尾的原理分析。
首先,我们先要了解Stage3D API基本原理之外的矩阵乘法,如果你求学时代已经学过大量的矩阵计算理论,那么你应该庆幸你当初学习的这部分知识并不是没用的花瓶,现在终于有了用武之地。

矩 阵乘法的基本理论是:一个mxn的矩阵A能够与一个nxr的矩阵B相乘,结果是一个mxr的矩阵。例如,一个4x2矩阵和一个2x3的矩阵相乘,结果是一 个4x3的矩阵C,C中的任意元素C[ij]就是A的第i行向量与B中的第j列向量的点乘结果。那么矩阵相乘的核心是:矩阵A的列,必须和矩阵B的行数量 匹配,否则矩阵乘法无意义。如果用图来表示,如下图:

在 Stage3D中,每一个Vertex顶点可以看做是一个1x3的矩阵[x,y,z],但是在3D环境中由于有齐次坐标w的存在,所以,我们经常将某个 vertex的坐标真正定义为1x4矩阵[x,y,z,w],如果w=1,表示将3D空间内的点都投影到w=1的4D平面上,齐次坐标公式是[x/w,y /w,z/w],由于w=1,所以自然也就成为我们平常所理解的[x,y,z]。而w=0的意义,则表示4D空间无穷远的点,自然也就成为了方向上的描 述,所以在Stage3D中的矩阵乘法,w坐标的0,就是顶点平移转换的开关。如果这里实在太难理解了,建议各位去wiki上仔细阅读一些基础3D理论。 所以,顶点变换的矩阵乘法是这样图示(缩放,旋转和平移可以自由设定4x4 Matrix3D矩阵中的行列值来获得):


谈到这里,就不难理解Stage3D顶点位置变换了。下面把基础理论,AGAL OpCode和Stage3D API揉在一起,看看一个基本的顶点变化操作,在Stage3D里怎么搞定的。AS代码:
基本AGAL Vertex顶点变换:
vertexShader=new AGALMiniAssembler();
vertexShader.assemble(Context3DProgramType.VERTEX,
"m44 op va0,vc0\n"+ //va0的vertex顶点坐标与vc0中的4x4 Matrix3D进行顶点变换的矩阵乘法,结果放在op位置输出寄存器中
"mov v0,va1\n" //va1的vertex 的UV或色彩值放置在v0中,v0则是vertex和fragment公用寄存器变量,这里va1取决于你的顶点Vector数据结构构成
);

Vertex顶点寄存器设定:
context3d.setVertexBufferAt(0,vertexBuffer,0,Context3DVertexBufferFormat.FLOAT_2);
context3d.setVertexBufferAt(1,vertexBuffer,5,Context3DVertexBufferFormat.FLOAT_3);
context3d.setVertexBufferAt(2,vertexBuffer,5,Context3DVertexBufferFormat.FLOAT_4);

顶点变换矩阵设定:
model3D.identity();
model3D.appendRotation(getTimer()/50,Vector3D.Z_AXIS);

//如有缩放,平移等3D空间内变换,需要将模型,视图和投影的Matrix3D进行总体矩阵相乘后得到最终的变换矩阵
//modelView3D.identity();
//modelView3D.append(model3D);
//modelView3D.append(view3D);
//modelView3D.append(projection3D);

context3d.setProgramConstantsFromMatrix(
Context3DProgramType.VERTEX,
0, model3D, true );//model3D可以换成modelView3D
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics