stage3d编程-基础5 初窥AGAL
周五晚上回家在家改了一晚上的bug.之前改了一下shader的结构,结构悲剧。。。有童鞋在问前一篇里面提到的模型的深度值是怎么计算的。其实呢,这个我没有提,这里面也是很大一个坑。这个深度值是通过projection算出来的。 projection我只是提了一下,然后给了一个实现链接。 这个深度值以后也会用到,比如说阴影啊之类的。
今天补上昨天的,初窥AGAL。之前给了一个demo.里面有两段AGAL。但是这个AGAL是什么呢?AGAL说白了,就是对显卡进行编程的指令。我们在写的时候,大家会看到类似汇编的mov之类的指令。 最终我们写的这些汇编级的代码,被通过adobe提供的agalassemble转换成二进制。注意这个二进制只能使用小头格式。应该是上传到gpu里面的二进制都只能使用小头格式。这里也是一个坑。因为as3默认的是大头。
1、stage3d中gpu可用的寄存器。 (一个寄存器由四个浮点数组成,也就是说一个寄存器的体积是四个浮点数。如果要取第一个浮点数,可以通过xyzw来取出。例如va.x, va.y, va.z)
va 寄存器。 va寄存器用于顶点着色器程序里面,属于输入流。一共8个,也就是va0,va1,va2,va3.....va7。在stage3d中。模型的顶点,uv,法线等数据全都是通过vertexbuffer上传的。va寄存器对应这vertexbuff的一段数据。有多少段数据,顶点程序就会执行多少次。顶点程序当前执行的数据来源,就是这一段数据。例如:
[
//X, Y, Z, U, V, nX, nY, nZ
-1, -1, 1, 0, 0, 0, 0, 1,
1, -1, 1, 1, 0, 0, 0, 1,
1, 1, 1, 1, 1, 0, 0, 1,
-1, 1, 1, 0, 1, 0, 0, 1
]
这块数据就是之前demo里面用到的数据。一共有四段。(注意看demo,我们在创建vertexbuffer的时候,就会指定一段数据的长度,数一下,一段8个)。那么顶点着色器程序在执行的流程:
某一段数据存到va寄存器,执行agal顶点程序的指令,然后执行片段着色器程序,执行很多次。大家在看demo的时候就会法线,有一段代码context3D.setVertexBufferAt(0, vertexBuffer, 0,Context3DVertexBufferFormat.FLOAT_3);那么这个过程呢,就是告诉顶点程序, 我使用了vertexBuffer这个顶点数据输入流。将vertexbuffer一段中,从第0个位置开始,取float_3也就是三个数据,当做va9寄存器的输入值。也就是将某一段的前面三个数据当存到了va0寄存器里面。前面这三个数据呢,就是我们指定的顶点坐标。我们也可以指定从第三个位置开始,取float_2,存到va1寄存器,那么这个值就是uv的数据了。context3D.setVertexBufferAt(1, vertexBuffer, 1,Context3DVertexBufferFormat.FLOAT_2);
vc 寄存器,vc寄存器同样也是顶点程序里面可用的寄存器。vc寄存器是常量寄存器,当设置好了vc寄存器的值以后,vc寄存器的值就不会在变化了,同样你也不能修改它的值。之前提到的va寄存器的值,是根据vertexbuffer的数据,一直在变的。类似一个for循环,for each(var va : * in vertexbuffer) {// 这里的va就会一段一段的变化}。但是vc寄存器在整个过程中,都是不会变的。就好比在for循环外面写了一个const vc = xxx。然后这个vc在for循环里面一直都是那个值,也不会变化,也不能被改变。大家看demo的时候就会发现以下一段代码:
context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX,0, modelViewProjection, true );这段代码就是在设置顶点程序的vc寄存器的值。注意看第一个参数。指定了vertex,第二个参数指定从vc里面哪一个寄存器开始。modelViewProjection则是一个矩阵。这是在设置矩阵常量,同样也可以设置vector.<number>常量。因为是设置的矩阵常量,那么之前就说到矩阵是4x4,那么就是16个浮点数,会占用4个寄存器。也就是说,这个0其实是指定的从哪一个vc寄存器开始。在这里vc0 vc1 vc2 vc3都被占用。如果是上传vector.<num>那么寄存器的使用同样也是根据传入的值的多少来决定。vc寄存器可以在agal里面通过[]符合来取。例如vc[0] vc[1] vc[2] vc[3]。但是也只有vc才行。这个功能是由adobe的那个agalassemble工具提供的。vc寄存器一共只有128个。 var vertexShaderAssembler:AGALMiniAssembler = new AGALMiniAssembler(); vertexShaderAssembler.assemble ( Context3DProgramType.VERTEX, // op是输出目标,va0是我们指定的顶点buffer中的数据,vc0是我们传入的modelViewProj矩阵。m44就是表示,用顶点乘以modelViewProj矩阵, "m44 op, va0, vc0\n" + // 将顶点传入中间变量寄存器,因为顶点程序和片段着色器程序是分开的,他们的数据不能通用,因此需要一个中间变量哎传递,并且这个是单向的,只能从顶点程序到片段程序 "mov v0, va0\n" + // 将指定的buffer中的数据1,也就是uv数据(后面再谈) "mov v1, va1\n" ); // 片段着色器程序,专门用来渲染颜色 var fragmentShaderAssembler:AGALMiniAssembler = new AGALMiniAssembler(); fragmentShaderAssembler.assemble ( Context3DProgramType.FRAGMENT, // grab the texture color from texture fs0 // tex是采样命令,意思就是根据uv数据从传入的贴图fs0安照<2d,repeat,miplinear>方式进行获取颜色信息,存放在ft0中 "tex ft0, v1, fs0 <2d,repeat,miplinear>\n" + // oc是颜色输出目标,将ft0传入oc进行输出了。 "mov oc, ft0\n" ); // 通过context3d创建着色器程序 shaderProgram = context3D.createProgram();<br> // 向显卡上传指令 shaderProgram.upload(vertexShaderAssembler.agalcode, fragmentShaderAssembler.agalcode);context3D.setTextureAt(0, myTexture);这一段代码,就是在设置fs寄存器和哪一个纹理图进行绑定。0表示下标,myTexture就是绑定的纹理。 即fs0是myTexture。 "tex ft0, v1, fs0 <2d,repeat,miplinear>\n" 。它的意思就是将fs0寄存器里面的那个纹理图,通过使用repeat,miplinear算法,根据v1(注意顶点程序的代码)的值(坐标值)进行采样,得到颜色信息存放到ft0寄存器。
浙公网安备 33010602011771号