使用缓冲区以及GLSL变量 - webGL 学习手记 | webGL 教程 (三)
前两篇的文章我们介绍了如何使用webGL进行简单的绘制,今天我们简单说一下如何使用缓冲区。
- DEMO预览
- http://zmofei.github.io/yes-webgl/demo/drawpoint.html
- DEMO源码
- https://github.com/zmofei/yes-webgl/blob/master/demo/drawpoint.html
- DEMO在线调试
- http://jsbin.com/vavude/1/edit
另外,我将学习过程中用到的一些资料放在了 Github 的 Yes-webGL https://github.com/zmofei/yes-webgl 项目上,如果大家有什么好的建议,或者愿意一同来写教程的欢迎来骚扰我。
何为缓冲区?
通过前面的例子,我们应该对webGl的渲染过程很熟悉了, 创建项目 -> 绑定shader -> 清除画布 -> 绘制画布
, 每次绘制钱我们都会去青春画布上的内容,然后进行新的绘制。但是,如果我们需要一次性绘制多个点或者多个图形怎么办呢?如果一个一个的去绘制的话,在性能上很有可能不尽人意,尤其是我们有千千万万个绘制点的时候。
这时候缓冲区
就开始刷存在感了,我们可以先将我们的数据存入到缓冲去,然后再一次性的把缓冲区的数据绘制出来。
一些封装
这个DEMO中,我们将获取WebGL上下文
,绑定着色器
等复杂的步骤进行了封装,如果想了解这两个步骤是如何工作的,请参考前两篇的文章。
缓冲区使用的步骤
现在步入正题,来看看我们DEMO中是如何处理这些细节的。
缓冲区使用非常简单,这里我们通过一下的步骤完成了缓冲区的创建、绑定、数据传入等工作
- 创建缓冲区
- 绑定缓冲区到WebGL对象
- 传入数据到缓冲区
1. createBuffer()
var vertexColorBuffer = gl.createBuffer();
创建缓冲区,这个很好理解,不用多说
2. bindBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, vertexColorBuffer);
将创建出来的缓冲区绑定到webGL对向上,这里我们使用了2个参数,第一个是类型,因为我们使用的是数组的点数据,所以使用系统提供的gl.ARRAY_BUFFER
变量。
第2个参数是我们需要绑定的Buffer对象,这里使用的就是我们第一步创建出来的Buffer对象。
3. bufferData()
var verticesColors = new Float32Array([
0.5, 0.5, 0,
-0.5, -0.5, 0,
-0.5, 0.5, 0,
0.5, -0.5, 0]);
//...
gl.bufferData(gl.ARRAY_BUFFER, verticesColors, gl.STATIC_DRAW);
这一步我们将我们的点位置数组传入到Buffer对象中 该方法接受的3个参数分别为
- 数据类型,可以是
gl.ARRAY_BUFFER
,gl.ELEMENT_ARRAY_BUFFER
,本例中使用的是gl.ARRAY_BUFFER
- 数据
- 缓冲类型,有这么几种可以供我们选择
GL_STREAM_DRAW
,GL_STATIC_DRAW
,GL_DYNAMIC_DRAW
GLSL 变量的使用
在本例中,我们通过js向定点着色器中传入了一些顶点坐标,那么这些坐标是如何赋值的呢?
var VSHADER_SOURCE =
'attribute vec4 a_Position;\n' +
'void main() {\n' +
' gl_Position = a_Position;\n' +
' gl_PointSize = 10.0;\n' +
'}\n';
首先看顶点着色器,我们声明了a_Position变量,接下来我们通过下面的方法进行赋值。
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
gl.vertexAttribPointer(a_Position, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(a_Position);
getAttribLocation(program, name)
在js中,我们首先通过getAttribLocation()获取到变量a_Position
在渲染器中的地址。
该方法接收两个变量
- program project对象
- name 变量名称
接下来我们通过vertexAttribPointer()方法,指定了如何处理渲染器中的值。
vertexAttribPointer(index, size, type, normalized, stride, offset);
比较复杂的一个方法
- index 绑定在gl.ARRAY_BUFFER中的目标索引,比较难理解,但是通常情况下我们可以通过getAttribLocation来获取这个值。
- size 每个属性的长度 [1,2,3,4(default)]
- type 类型 指定数据类型 我们有两个选择,[gl.FLOAT (default)|gl.FIXED]
- normalized 是否初始化传入的数据 [gl.FALSE|gl.TRUE]
- stride 每组数据的个数,[0-255]
- offset 这一组中的数据起始位置(从0开始)
接下来启用 enableVertexAttribArray()
enableVertexAttribArray(index);
- index 同 vertexAttribPointer中的index
##总结
OK,目前为止我们已经学会了WebGL的非常基本的知识,接下来,我们尝试真正的迈入3D的学习。