zoukankan      html  css  js  c++  java
  • Flash Stage3D Molehill 学习笔记(3)

      前面已经了解了一些Stage3D的基础与工作原理,今天我准备继续深入了解下隐藏于Stage3D API背后的神秘代码 AGAL。

      废话不多说直接进入主题,老规矩先搞清楚什么是AGAL? AGAL是干什么的?

      AGAL(Adobe Graphics Assembly Language)是Adobe开发的图形汇编语言,汇编语言是仅高于计算机二进制机器码的低级语言,可以精确地操控机器硬件比如可编程显卡,PC的Dirext9、MAC的OpenGL以及移动设备中的OpenGL ES 2都是可编程显卡,并且都支持AGAL。通过Adobe官方提供的编译器AGALMiniAssembler(实际上是一个AS类库),我们可以通过字符串指令来获得一个AGAL二进制流,再通过context3D上传给显卡的编程管线。对于顶点以及片段的运算都是通过AGAL交由显卡来处理的,这就是传说中的GPU硬件加速。),最新的测试版flash player 11中提供了可调用显卡资源来渲染图形API.
    这个百度里以及很详细了,有兴趣可以去了解下 http://baike.baidu.com/view/6423021.htm
    AGAL代码结构
      <opcode> <destination> <source1> <source2>
      <操作码>   <目标>       <来源1>     <来源2或样例>
      opcode:表示执行什么指令或函数,而这个指令或者函数被称作“操作码”。
      destination:表示运算的结果要去的“目的地”。
      source1与source2:数据源的位置。
      例: mov v0, v1 表示将存于 va1 中的值复制到 v0。
      AGAL有大约30种不同的操作码。完整的操作码列表如下:
      

    名称 描述 说明

    mov 移动 移动 source1 数据到 destination

    add 相加 destination = source1 + source2

    sub 相减 destination = source1 - source2

    mul 相乘 destination = source1 * source2

    div 相除 destination = source1 / source2

    rcp 倒数 destination = 1 / source1

    min 最小值 destination = minimum(source1 , source2)

    max 最大值 destination = minimum(source1 , source2)

    frc 取小数 destination = source1 - (float) floor(source1)

    sqt 平方根 destination = sqrt(source1)

    rsq 平方根倒数 destination = 1 / sqrt(source1)

    pow 指数 destination = pow(source1 , source2)

    log 2 为底的对数 destination = log_2(source1)

    exp 2 为底的指数 destination = 2^source1

    nrm 标准化 destination = normalize(source1)

    sin 正弦 destination = sin(source1)

    cos 余弦 destination = cos(source1)

    abs 绝对值 destination = abs(source1)

    neg 负值 destination = -source1

    sat 饱和值 destination = maximum(minimum(source1 , 1) , 0)

    kil 抛弃(只限片断着色器) 假如单一分量小于 0 便放弃绘图

    tex 材质取样(只限片断着色器) 依据 source1 坐标从 source2 材质取样

    sge 分量运算(set-if-greater-equal) destination = source1 >= source2   1 : 0

    slt 分量运算(set-if-less-than) 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 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 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 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)

    ifz, inz, ife, ine, ifg, ifl, ieg, iel, els, eif, rep, erp, brk, sgn 从AGALMiniAssembler里面看到还有这些opcode ifz, inz, ife, ine, ifg, ifl, ieg, iel, els, eif, rep, erp, brk, sgn 不过实际测试发现在目前这版 Flash Player 尚未支持

    AGAL Registers 缓存器

    缓存器 定义 权限

    顶点着色器 片断着色器 AS3编译器

    vc0 - vc127 顶点矩阵常量 读 写

    va0 - va7 顶点缓冲属性 读 写

    vt0 - vt7 顶点临时变量 读/写

    op 顶点着色器最终输出的对象 写

    v0 - v7 变量 写 读

    fc0 - fc27 片断常量 读 写

    ft0 - ft7 片断临时变量 读/写

    fs0 - fs7 片断纹理采样器 读/写

    oc 片断着色器最终输出的对象 写

     什么是寄存器:
      <destination>、<source1>与 <source2> 都被称为“寄存器”。也以把它理解成 AS3中的变量,它是用来存储数据的地方。它们各自指向一小块显存,由于进行过优化,因此访问速度非常快。为了达到最快的速度,AGAL所提供的寄存器是有数量限制的。当你开始编写那些更为复杂的着色器时,你就会经常把它们用光,而不得不提出创出新的方法就是重用寄存器。
      从String到Vector3D再到Bitmap,AS3变量有着各种各样的数据格式。但与此相反,寄存器全部都是128bit的容量,并且包含有4个浮点数。这4个值又被称为4个分量。可以通过使用x,y,z,w或者r,g,b,a来单独访问一个分量。每个操作码都是按“分量形式”的方式执行指令。这意味着它们会按顺序,把寄存器分量一个一个的分别加到一起。
      例:add va0, va1; 这句指令执行了add 操作码,显卡就会把 va0.x和va1.x相加,然后是 va0.y 和 va1.y,va0.z 和 va1.z,最后是 va0.w 和 va1.w。
      假设 va0 = (20,50,10,0);
         va1 = (50,5,0,1);
      则执行add指令结果 = (70,55,10,1)
     
    Attribute Registers  属性寄存器

    这些寄存器涉及顶点着色器的输入VertexBuffer。因此,他们只可用在顶点着色器。

    为了指派一个VertexBuffer到指定的属性寄存器,在这个函数中使用正确的索引号Context3D::setVertexBufferAt()。

    从着色器中访问该属性寄存器的语法:va<n>,其中<n>是属性寄存器的索引号。

    总共有8个用于顶点着色器的属性寄存器。

    Constant Registers 常量寄存器

    这些寄存器是为了从ActionScript传递参数到着色器。通过Context3D::setProgramConstants()函数完成。

    从着色器中访问这些寄存器的语法:vc<n>,用于顶点着色器,fc<n>,用于像素着色器,其中<n>是常量寄存器的索引号。
    有128个用于顶点着色器和28个用于像素着色器的常量寄存器。

    Temporary Registers  临时寄存器

    这些寄存器供着色器在临时计算时使用。
    访问它们的语法:vt<n>(点)和 ft<n> (像素),其中<n>是寄存器的序号。
    有8个可用于顶点着色器,8个可用于像素着色器。
    Output Registers 输出寄存器

    输出寄存器存储顶点和像素着色器的计算输出。对于顶点着色器是一个顶点剪辑空间的位置。对于像素着色器是该像素的颜色。
    访问这些寄存器的语法:op,用于顶点着色器,oc,用于像素着色器。
    显然只有一个用于顶点和像素着色器的输出寄存器。
     Varying Registers 变量寄存器
    这些寄存器用来从顶点着色器向像素着色器传递数据。
    这些寄存器用来传递从顶点​​着色器到像素着色器的数据。所传数据被GPU转换,从而使像素着色器接收到正确的值,用于正在处理的像素。
    用这种方法传递的典型数据是顶点的颜色或纹理的UV坐标。
    访问这些寄存器的语法:v<n>,其中<n>是寄存器序号。
    有8个变量寄存器可用。

    Texture Samplers  纹理采样寄存器
    纹理采样寄存器是用来接收从基于UV坐标系的纹理中的颜色值。
    纹理的指定通过ActionScript使用方法 Context3D::setTextureAt()。
    纹理采样的使用语法是:ft<n> <flags>,其中<n>是采样序号,<flags>是一个或多个用于指定应如何取样的标志集。

    <flags>是一个以逗号分隔的字符串集,其定义是:

    纹理维度。可以是:2d, 3d, cube
    多重材质映射。可以是:nomip, mipnone, mipnearest, mipnone
    纹理滤镜。可以是:nearest, linear
    重复纹理。可以是:repeat, wrap, clamp.
    好了,举例来说,一个标准的没有多重材质映射的2D纹理,进行线性滤镜采样到临时寄存器ft1中,用下行:
    “tex ft1, v0, fs0 <2d,linear,nomip> “
    其中变量寄存器v0保存以内插值替换的纹理UV坐标。
    顶点和像素着色器例子解释
    现在我们返回到着色器的例子,并解释其运作。
    我们假设顶点在VertexBuffer中包含着顶点的位置,偏移量是0,纹理的UV偏移量是3。
    我们希望我们的顶点着色器转换顶点位置到剪辑空间里,并传递UV到像素着色器。
    执行以下代码:
    m44 op, va0, vc0 // pos to clipspace
    mov v0, va1 // copy uv
    第一行执行了在输入顶点,va0,和从模型空间到剪辑空间的变换矩阵之间的4×4矩阵乘法,我们假定已从ActionScript写入到常量寄存器0中,vc0。
    用下面的方法可将此矩阵写入到着色器:
    Context3D::setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, matrix, true );
    着色器的第二行,复制顶点UV数据到变量寄存器0,V0,因此,它可以获得修正,并传递到像素着色器。
    像素着色器采样纹理,并复制颜色到输出寄存器。
    tex ft1, v0, fs0 <2d,linear,nomip>
    mov oc, ft1
    好了,这个顶点/像素着色器刚刚将三维模型转换到二维屏幕上,并进行了纹理映射。
    这就是我们的第一个顶点和像素着色器!
  • 相关阅读:
    递归获取指定盘符下的所有文件及文件夹
    单例模式和多线程有没有关系?
    eclipse启动tomcat时设置端口
    dozer转化对象
    枚举
    dubbo
    json
    配网失败问题
    esp_err_t esp_event_loop_init(system_event_cb_t cb, void *ctx);
    base64编码
  • 原文地址:https://www.cnblogs.com/ch06src/p/3132396.html
Copyright © 2011-2022 走看看