【学习笔记】3D图形核心基础精炼版-10:stage3D实战-AGAL基础和命令

来源:互联网 发布:windows pe 知乎 编辑:程序博客网 时间:2024/05/17 03:58

1、AGAL是stage3D的着色语言,分为顶点着色(vertex shader)和片段着色(fragment shader)

2、顶点着色主要用于输出顶点位置,以及传递vertexBuffer上的信息到片段着色器使用,所以也可以在这里计算一些信息,比如挪动顶点位置。

3、片段着色主要用于输出颜色信息,比如贴图中的像素颜色,所以在这里可以更改颜色,比如叠加一个颜色或设计光照效果等。

简单示例:简单的直接输出每个顶点以及每个顶点对应的颜色信息,系统会自动插值补充,所以你看到的东西并不仅仅只有顶点,并且颜色由于插值也会看到渐变效果
                    同理,如果你要计算一个顶点的其他信息,系统会同样插值出来,比如当前点到对边的距离。

// -- 创建一个着色语言program = context3d.createProgram();// -- 创建一个AGALMiniAssembler辅助类用于写顶点着色代码//    主要用于输出最终的顶点位置,以及传一些数据给片段着色代码使用var vShader:AGALMiniAssembler = new AGALMiniAssembler();vShader.assemble(Context3DProgramType.VERTEX,"m44 op va0 vc0 \n" + // 输出 = 4个顶点 * 最终矩阵 (这里的*就是m44方法,表示每个点都作用了该矩阵)"mov v1 va1\n" // 将4个点的颜色传到中转站以便片段着色代码使用);// -- 创建一个AGALMiniAssembler辅助类用于写片段着色代码var fShader:AGALMiniAssembler = new AGALMiniAssembler();fShader.assemble(Context3DProgramType.FRAGMENT,"mov oc v1" // 输出 = 颜色信息(当然这里是4个点的颜色信息了));program.upload(vShader.agalcode,fShader.agalcode);

关于寄存器使用:为了适应最低端设备和显卡,限制了数量。

1、每个寄存器占16个字,即4个float型,在AS3里则表现为4个Number型
2、通过 x,y,z,w 或 r,g,b,a 可以访问寄存器中的4个float型数值(元素),如va1.x 和 va1.r 都表示va1中的第一个元素,寄存器运算时各个元素对应


顶点着色器(vertex shader)用的寄存器:

   "va 属性寄存器:"
va0,va1,....,va7  一共8个,来自vertexBuffer中传递进来的,一般传递顶点坐标、顶点颜色、顶点法线、顶点贴图UV坐标

   "vc 常量寄存器: " vc0,vc1,....,vc127 共128个 ,传递进来的常量,因为AGAL中不能直接输入一个常量,必须传递进来才能使用,是比较蛋疼
 
   "vt 临时寄存器: " vt0,vt1,...,vt7,一共8个,也就是说临时变量,就像AS3中 var a0:int  一样,但这里最多8个

   "op 输出寄存器: " op  输出顶点,例如mov op, va0

片段着色器(fragment shader)用的寄存器:

   "fs 纹理采样寄存器" fs0,fs1,...,fs7   用于记录纹理中的像素

   "fc 常量寄存器" x,y,z,w 28个 用于在片段着色器中使用的常量

   "ft 临时寄存器" 0-7  用于在片段着色器中使用的临时变量

   "oc 输出寄存器" 输出颜色信息,例如 mov oc,ft0

  

共用寄存器:
   
 "v 插值寄存器" v0,v1,...,v7  在顶点着色器和片段着色器都能用的,如果你需要从片段着色器中传递顶点的颜色信息等数据可以放到这里

AGAL相关命令:

"mov"  0x00  移动   将数据从 source1 移动到 destination,按组件  "add"  0x01  相加   destination = source1 + source2,按组件 "sub"  0x02  相减   destination = source1 - source2,按组件 "mul"  0x03  相乘  destination = source1 * source2,按组件 "div"  0x04  除以  destination = source1 / source2,按组件 "rcp"  0x05  倒数  destination = 1/source1,按组件 "min"  0x06  最小值  destination = minimum(source1,source2),按组件 "max"  0x07  最大值  destination = maximum(source1,source2) destination = maximum(source1,source2),按组件 "frc"  0x08  分数  destination = source1 ? (float)floor(source1) destination = source1 ? (float)floor(source1),按组件 "sqt"  0x09  平方根  destination = sqrt(source1),按组件 "rsq"  0x0a  平方根倒数  destination = 1/sqrt(source1),按组件 "pow"  0x0b  幂  destination = pow(source1,source2),按组件 "log"  0x0c  对数  destination = log_2(source1),按组件 "exp"  0x0d  指数  destination = 2^source1,按组件 "nrm"  0x0e  标准化  destination = normalize(source1),按组件(仅生成一个 3 组件结果, 目标必须遮罩为 .xyz 或更小) "sin"  0x0f  正弦  destination = sin(source1),按组件 "cos"  0x10  余弦  destination = cos(source1),按组件 "crs"  0x11  叉积  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                 (仅生成一个 3 组件结果,目标必须遮罩为 .xyz 或更小) "dp3"  0x12  点积  destination = source1.x*source2.x + source1.y*source2.y + source1.z*source2.z "dp4"  0x13  点积  destination = source1.x*source2.x + source1.y*source2.y + source1.z*source2.z + source1.w*source2.w "abs"  0x14  取绝对值  destination = abs(source1),按组件 "neg"  0x15  求反  destination = -source1,按组件 "sat"  0x16  饱和  destination = maximum(minimum(source1,1),0),按组件 "m33"  0x17  矩阵连乘3×3  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)                      (仅生成一个 3 组件结果,目标必须遮罩为 .xyz 或更小) "m44"  0x18  矩阵连乘4×4 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"  0x19  矩阵连乘3×4  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)                     (仅生成一个 3 组件结果,目标必须遮罩为 .xyz 或更小) "kil"  0x27  丢弃  如果单个标量源组件小于零,则将丢弃片段并不会将其绘制到帧缓冲区。  "只在片段着色器使用" (目标寄存器必须全部设置为 0) "tex"  0x28  纹理取样  destination 等于从坐标 source1 上的纹理 source2 进行加载。在这种情况 下, source2 必须采用取样器格式 "sge"  0x29  大于等于时设置  destination = source1 >= source2 ? 1 : 0,按组件 "slt"  0x2a  小于时设置  destination = source1 < source2 ? 1 : 0,按组件 "seq"  0x2c  相等时设置  destination = source1 == source2 ? 1 : 0,按组件 "sne"  0x2d  不相等时设置 destination = source1 != source2 ? 1 : 0,按组件

现在再次回头看看那个简单示例,就会明白,在顶点着色器中主要是为了输出顶点信息,由于顶点都是相对0,0,0点的坐标点,为了让此次渲染的物体根据它当前的变换(平移、缩放、旋转等)将点画在屏幕的对应的地方上,就要m44作用一下最终矩阵(M模型变换+V相机变换+P投影变换),这样才能区分出同一个屏幕不同物体出现的位置、大小、旋转不一样。
m44 op va0 vc0

然后由于这里没有使用纹理,所以我们将颜色信息传递过去给片段着色器用,因为顶点颜色信息我们之前是直接放在vertexBuffer里的,对应了每个顶点的颜色信息,由于插值寄存器是共用的,所以片段着色器就能用了
mov v1 va1

我们不对颜色进行任何改变、叠加等效果,我们就只是输出每个顶点的颜色,所以在片段着色器中就直接输出了

mov oc v1

如果你想要扩展下的话,比如在原有的颜色基础上,叠加一次,比如颜色点R=100 G=50 B=0,叠加为R=100+100 G=50+50 B=0+0,那么你可以将上面的那行替换下

"mov ft0 v1\n" + // 拿一个临时变量ft0记录下原始颜色信息"add ft0 ft0 ft0\n" + // ft0 = ft0 + ft0 也就是说原来的RGB变为 2R 2G 2B(...呵呵)"mov oc ft0" // 再输出
当然,你得将颜色改为0.5以下才方便对比出来,比如0.5,0.5,0,如果直接输出的话是暗黄色(R=0.5 G=0.5 B=0),如果叠加了就是亮黄色(R=1 G=1 B=0),因为最大不会超过1,即使超过了仍然也就是1的效果。

实际对比效果:左边是4个顶点颜色最多是0.5的直接输出,右边在片段着色器里进行了颜色处理(自己和自己叠加)
  
    

0 0