目标:
1.了解缓冲区对象的使用,以及如何将多个顶点数据同时传递给顶点着色器。
2.使用WebGL的缓冲区对象来绘制三角形。
使用缓冲区对象:
缓冲区对象是在webgl系统中的一块存储区,他可以把你所有想要绘制的顶点保存进去,那么你就可以一次性地向顶点着色器中传入多个顶点地attribute变量的数据。
向顶点着色器传入多个顶点数据需要遵循以下五个步骤:
下面详细的解释每一步的具体细节。
1.创建缓冲区对象:
var vertexBuffer = gl.createBuffer();
在使用之前,你必须创建它。上句代码执行后状态:
2.绑定缓冲区:
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
下面是函数规范:
我们将缓冲区对象绑定到了gl.ARRAY_BUFFER,此时缓冲区对象里存储着顶点数据,上句执行完后的状态:
接下来就可以向缓冲区对象写数据了。
3.向缓冲区对象写数据。
var vertices = new Float32Array([-0.5, -0.5, 0.5, -0.5, 0.0, 0.5])
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
第一行就是三个顶点数据(x,y),第二行就是将数据写入缓冲区。
Float32Array是webgl里的一种类型化数组,webgl通常需要同时处理大量同类型的元素,所以大家知道运用这个的目的是优化性能就可以了。
执行后的状态:
4.将缓冲区对象分配给attribute变量:
gl.vertexAttribPointer(position, 2, gl.FLOAT, false, 0, 0)
vertexAttribPointer () 可以将多个顶点数据一次性的传递给一个attribute变量。上面是我的代码所用,具体规范如下(注意重点看一下size和stride、offset):
(本篇文章绘制三角形只使用了顶点坐标)如果当我们把顶点的坐标和尺寸同时写入缓冲区时上图就是其存储的格式。两种不同类型的数据就需要stride和offset来帮助webgl来分辨。如上图每三个元素是一个顶点的有关数据,前两个是坐标(白色),后一个是尺寸(黑色),那么stride由定义就需要乘三,offset就需要乘二。所以我们需要得到数组中每个元素的字节数:
let FSIZE = vertices.BYTES_PER_ELEMENT;
5.开启attribute变量:
gl.enableVertexAttribArray(position)
执行后,缓冲区对象就与attribute真正的连接了起来
接下来就是让顶点着色器运行起来,利用gl.drawArrays函数。
gl.drawArrays(gl.TRIANGLES, 0, 3);
规范参数:
下面是所有的js代码及效果图:
var vsSource = `
attribute vec4 a_Position;
attribute float a_PointSize;
void main(void){
gl_Position = a_Position;
}
`;
var fsSource = `
void main(void){
gl_FragColor = vec4(1.0,0.0,0.0,1.0);
}
`;
var gl;
function init() {
main();
initShaders();
initBuffers();
drawScene();
}
function main() {
var canvas = document.getElementById('glcanvas');
gl = canvas.getContext('webgl');
}
function initShaders() {
let vsshader = gl.createShader(gl.VERTEX_SHADER);
let fsshader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(vsshader, vsSource);
gl.shaderSource(fsshader, fsSource);
gl.compileShader(vsshader);
gl.compileShader(fsshader);
let program = gl.createProgram();
gl.attachShader(program, vsshader);
gl.attachShader(program, fsshader);
gl.linkProgram(program);
gl.useProgram(program);
gl.program = program
}
function initBuffers() {
var position = gl.getAttribLocation(gl.program, 'a_Position');
var vertexBuffer = gl.createBuffer();
var vertices = new Float32Array([-0.5, -0.5, 0.5, -0.5, 0.0, 0.5])
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
gl.vertexAttribPointer(position, 2, gl.FLOAT, false, 0, 0)
gl.enableVertexAttribArray(position)
}
function drawScene() {
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLES, 0, 3);
}
最后:
下一篇文章会比较难,涉及的知识有很多,建议大家可以先去了解一下图形学关于矩阵变换的知识。