WebGL入门教程三:更灵活的数据传递和绘制图形
作者:心叶
时间:2018-05-16 10:55
绘制三个点
前一篇文章我们绘制了一个点,现在想绘制三个点,怎么办?
当然,你可以按照绘制一个点的方法,绘制三次,不过我们这里来说说如何一次绘制三个点。
在前面代码的基础上,我们只需要修改传递点的个数,然后修改绘画方法就可以了。
传递三个点
之前【传递点的位置】处的代码的传递方法只可以传递一个点,如果想传递三个点,需要使用缓冲区。
因此,我们第一步要创建一个缓冲区,并且把点的数据写入缓冲区,代码如下(注释调原来【传递点的位置】的代码,在相同位置添加):
//1.创建缓冲区对象 var vertexBuffer = gl.createBuffer(); // 2.绑定缓冲区对象(表明了缓冲区对象的用途) gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); // 3.向缓冲区对象中写入数据 var tempData=new Float32Array([ 0.0, 0.5, -0.5, -0.5, -0.5, 0.5 ]); gl.bufferData(gl.ARRAY_BUFFER, tempData, gl.STATIC_DRAW);
这样,缓冲区就准备好了,接着,把缓冲区和着色器联系起来:
// 4.获取变量存储位置 var a_Position = gl.getAttribLocation(glProgram, 'a_Position'); // 5.把缓冲区对象分配给a_Position变量 gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0); // 6.连接缓冲区对象和a_Position变量 gl.enableVertexAttribArray(a_Position);
这样,点的位置就传递好了。
修改绘图方法
现在,修改一下绘图方法:
gl.drawArrays(gl.POINTS, 0, 3);
刷新页面,应该可以看见下图:
绘制三个不同大小的点
数据修改
首先,我们要在缓冲区或准备一下数据,表示每个点的大小,对应代码修改如下:
var tempData=new Float32Array([ 0.0, 0.5, 10.0, -0.5, -0.5, 20.0, -0.5, 0.5,30.0 ]); //这个是每个数据大小,辅助用的 var FSIZE = tempData.BYTES_PER_ELEMENT;
传递点位置的方法修改
由于数据重新调整了,缓冲区分配给点位置的变量也要对应调整:
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, FSIZE*3, 0);
不清楚的可以去百度一个vertexAttribPointer这个方法,后面我们会统一说明一些常用方法,这里就不说了。
现在,你刷新页面,应该和之前的一样。
传递点大小的方法修改
和上面类似,之前传递一个点大小,现在传递三个就可以了:
//【传递点的大小】 var a_PointSize=gl.getAttribLocation(glProgram,'a_PointSize'); //之前传递一个的方法注释调了 // gl.vertexAttrib1f(a_PointSize,30.0); gl.vertexAttribPointer(a_PointSize, 1, gl.FLOAT, false, FSIZE*3, FSIZE*2); gl.enableVertexAttribArray(a_PointSize);
现在刷新页面,应该就可以了:
绘制三角形
普通三角形
到目前为止,传递多个点应该没有问题了吧,如果想绘制复杂图形,调用对应api就可以了,比如绘制三角形,修改最后一个绘制方法(绘制三角形的话,点的大小就没有意义了,可以删除,留着也没事):
// gl.drawArrays(gl.POINTS, 0, 3); gl.drawArrays(gl.TRIANGLES, 0, 3);
结果如下:
彩色三角形
既然位置可以传递多个,是不是颜色也可以,是的,也可以。
同样的,我们先添加颜色数据:
var tempData=new Float32Array([ 0.0, 0.5, 10.0,1.0,0.0,1.0, -0.5, -0.5, 20.0,0.0,1.0,0.0, -0.5, 0.5,30.0,0.0,0.0,1.0 ]);
修改缓冲区绑定位置的方法:
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, FSIZE*6, 0);
由于要传递三个点,uniform只可以传递一致的数据,因此我们需要用attribute,可是attribute有只可以用在顶点着色器,因此,需要先传递改顶点着色器,然后借助varying传递给片段着色器,着色器修改如下(点的大小代码就没有删除了):
<!-- 顶点着色器 --> <script type='x-shader/x-vertex' id='shader-vs'> attribute vec4 a_Position; attribute float a_PointSize; attribute vec4 a_Color; varying vec4 v_FragColor; void main(){ gl_Position=a_Position; gl_PointSize=a_PointSize; v_FragColor=a_Color; } </script> <!-- 片段着色器 --> <script type='x-shader/x-fragment' id='shader-fs'> precision lowp float; varying vec4 v_FragColor; void main(){ gl_FragColor=v_FragColor; } </script>
然后,和点的位置一样,修改传递色彩的代码:
// 【传递点的颜色】 var a_Color = gl.getAttribLocation(glProgram, 'a_Color'); // gl.uniform4f(u_FragColor,1.0,0.0,0.0,1.0); gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, FSIZE * 6, FSIZE * 3); gl.enableVertexAttribArray(a_Color);
显示效果如下: