用stage3D API绘制四边形
网上介绍stage3D基本API的文章基本都是以画三角形为案例。对于了解3D图形学的人来说很清楚怎么用这些API绘制一个四边形,但对于刚入门的人来说,虽然只是多了一个点,但如果运气不好可能要费很大的劲。
我们知道stage3D API能绘制的最基本的图形元素是三角形,任何复杂的图形都要首先转化成若干个三角形才能用这些API来绘制。那么对于一个四边形,很显然,我们可以将它分解成两个三角形,如下图所示:
1------2
| / |
0------3
四边形的四个顶点为0,1,2,3。这四个数字只是用来标记他们(顶点索引)并不具有实际的几何意义,为了绘制他们,还需要给他们定位,即给他们各自指定一个坐标,可以指定任意的值,但是要在保证这四个点在空间的基本关系不变,即顺时针的顺序。
为了简便起见,同时也不失一般性,我们将这四个点放置在z平面上,他们之间构成一个矩形:
1 vertexBuffer = context3D.createVertexBuffer(4,6); 2 3 vertexBuffer.uploadFromVector(Vector.<Number>([ 4 -1,-1,1,1,0,0, 5 1,-1,1,0,1,0, 6 1,1,1,0,0,1, 7 -1,1,1,0,1,1 8 ]),0,4);
上面两段代码中,第一行的意思是创建一个4个点,每个点有6个数据的顶点缓冲,这6个数据分别为:前三个顶点坐标,后三个顶点颜色。后面一段代码是将数据上传到顶点缓冲。
紧接着,我们将他们绑定到属性寄存器上:
1 context3D.setVertexBufferAt(0,vertexBuffer,0,Context3DVertexBufferFormat.FLOAT_3); 2 context3D.setVertexBufferAt(1,vertexBuffer,3,Context3DVertexBufferFormat.FLOAT_3);
这样我们就可以通过属性寄存器va0,va1分别访问到顶点位置和颜色数据。
至此四个顶点的数据就处理完毕了,接下来需要指定以怎样的顺序绘制他们,这就是索引寄存器的作用了:
1 indexBuffer = context3D.createIndexBuffer(6); 2 indexBuffer.uploadFromVector(Vector.<uint>([ 3 0,1,2,2,3,0 4 ]),0,6);
以上两段代码的第一行创建一个大小为6的索引缓冲,后面的代码将一组数据上传到这个缓冲里,需要注意:这些数据没三个一组,每一组构成一个三角形,并且每一组的顶点顺序是一致的,即要么都为顺时针 要么都为逆时针,因为我们将问题简化为一个平面所以比较简单,在复杂的曲面图形中需要解释的就多一些,这些以后遇到再说。
以上就是绘制一个四边形的核心内容了,至于接下来的内容,基本上同绘制三角形一样:
指定透视投影矩阵:
1 var pm:PerspectiveMatrix3D = new PerspectiveMatrix3D(); 2 3 //pm.perspectiveLH(5,5,1,10000); 4 pm.perspectiveFieldOfViewLH(1,stage.stageWidth/stage.stageHeight,1,10000); 5 context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX,0,pm,true);
编写着色器:
var vertexAssembler:AGALMiniAssembler = new AGALMiniAssembler(); var fragmentAssembler:AGALMiniAssembler = new AGALMiniAssembler(); var vertexSrc:String = "m44 op,va0,vc0 \n" + "mov v0,va1"; var fragmentSrc:String = "mov oc,v0"; vertexAssembler.assemble(Context3DProgramType.VERTEX,vertexSrc); fragmentAssembler.assemble(Context3DProgramType.FRAGMENT,fragmentSrc);
创建程序,绘制:
var program:Program3D = context3D.createProgram();
program.upload(vertexAssembler.agalcode,fragmentAssembler.agalcode); context3D.setProgram(program); context3D.drawTriangles(indexBuffer); context3D.present();
结束!