webgl——VAO

来源:互联网 发布:红圈通是什么样的软件 编辑:程序博客网 时间:2024/06/01 09:32

        上次说到了对VAO、VBO的理解,明白了使用VAO相比传统模式在IO方面对加载性能的提升,今天我对其在WebGL上进行了实现。

        在WebGL中由于很多API与OpenGLES大为不同(一般常用的API大致是相同的),开始时费了很多劲,最后还是通过MSDN找到了相关的API及方法,这里对设计VAO的主要的部分进行介绍,对VAO还不是很理解的同学可以看这篇文章:http://blog.csdn.net/srk19960903/article/details/74999018

        这次我们还用的是上次那个篮球在地面上弹的例子,只是把篮球和地面加载的部分换成了VAO方法,篮球阴影的加载还使用的是传统方法,以便于对照。

function ObjObject  (     gl,                    //GL上下文     vertexDataIn,    //顶点坐标数组     vertexNormalIn,   //顶点法向量数组     vertexTexCoorIn,  //顶点纹理坐标数组     programIn          //着色器程序对象  )  {         //加载着色器程序         this.program=programIn;         this.ext = gl.getExtension("OES_vertex_array_object");         //create VAO         this.vao = this.ext.createVertexArrayOES();         // bind vao         this.ext.bindVertexArrayOES(this.vao);     //接收顶点数据     this.vertexData=vertexDataIn;     //得到顶点数量     this.vcount=this.vertexData.length/3;     //创建顶点数据缓冲     this.vertexBuffer=gl.createBuffer();       gl.bindBuffer(gl.ARRAY_BUFFER,this.vertexBuffer);       gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(this.vertexData),gl.STATIC_DRAW);         var apos = gl.getAttribLocation(this.program, "aPosition");         gl.vertexAttribPointer(apos, 3, gl.FLOAT, false, 0, 0);         //启用顶点数据         gl.enableVertexAttribArray(apos);         //此处省略法线和纹理坐标的数据         this.ext.bindVertexArrayOES(null);}

        这里可以看到在初始化的部分代码明显变多,主要是因为将每次传递顶点、法线、纹理坐标位置的数据从drawSelf移到了初始化函数中,这里值得一提的是,在OpenGLES中的Gen开头的API在WebGL中都没有,取而代之的是gl.getExtension("OES_vertex_array_object");然后创建VAO并对其进行绑定,最后在完成之后取消绑定。还有就是一定要注意顺序,每次创建数据缓冲、启用顶点数据和绑定缓冲的代码必须一次完成,之前我写的时候总是报:

WebGL GL ERROR :GL_INVALID_OPERATION : glDrawElements: attempt to access out of range vertices in attribute 1

这个错就是因为顺序不对,导致在最后绘制的时候数据溢出了。

        下面是drawSelf的方法:

    this.drawSelf=function(ms,texture)    {           gl.useProgram(this.program);//指定使用某套着色器程序(重要)   //送入总矩阵var uMVPMatrixHandle=gl.getUniformLocation(this.program, "uMVPMatrix");   gl.uniformMatrix4fv(uMVPMatrixHandle,false,new Float32Array(ms.getFinalMatrix()));          //送入变换矩阵         var uMMatrixHandle=gl.getUniformLocation(this.program, "uMMatrix");         gl.uniformMatrix4fv(uMMatrixHandle,false,new Float32Array(ms.currMatrix));                   //送入光源位置         var uLightLocationHandle=gl.getUniformLocation(this.program, "uLightLocation");         gl.uniform3fv(uLightLocationHandle,new Float32Array([lightManager.lx,lightManager.ly,lightManager.lz]));                  //送入摄像机位置         var uCameraHandle=gl.getUniformLocation(this.program, "uCamera");         gl.uniform3fv(uCameraHandle,new Float32Array([ms.cx,ms.cy,ms.cz]));           //绑定纹理           gl.bindTexture(gl.TEXTURE_2D, texture);           this.ext.bindVertexArrayOES(this.vao);//用顶点法绘制物体   gl.drawArrays(gl.TRIANGLES, 0, this.vcount);     }    
        这次在传递完uniform的参数之后,直接打开了bindVertexArrayOES,使用其中的数据当做绘制时需要用的顶点数据、法线数据、纹理坐标数据,这样在每次绘制时就不用再次传递了。

        实现的效果与阴影那片相同,主要是将obj加载方法换成了VAO的方式。

        下面是Github地址:https://github.com/StringKun/WebGL-VAO

        



原创粉丝点击