本专栏所有文章示例代码均可在我的gitee码云上获取,读者可自行下载:https://gitee.com/babyogl/learnWebGL;本文demo代码在chapter-03下的rectangle-01.html,读者可以自行下载查看;
前面三节笔者分别实现了:用WebGL绘制一个三角形,WebGL中的矩阵运算:平移、旋转和缩放, WebGL绘制矩形等几个demo,也许细心的读者会发现代码很凌乱,而且实现一个例子往往需要很多行代码,那有没有更简洁的代码表达方式?当然有,我们可以把复用多次的代码封装起来。
我们将寻找着色器变量的位置和创建的缓冲区作为着色器项目的一个属性,这样做可以方便参数的传递:
//创建着色器程序
let program = initShader(gl, vShaderSource, fShaderSource);
program.pLocation = getAttribute(gl, program, 'a_position');
program.rLocation = getUniform(gl, program, 'u_resolution');
program.cLocation = getUniform(gl, program, 'u_color');
//创建缓冲区
program.pBuffer = gl.createBuffer();
我们将菜单栏编写为一个函数initGui接受gl和program两个参数,从这里就可以看出步骤1的好处:
function initGui(gl, program) {
let gui = new dat.GUI();
gui.add(guiField, 'x', 0, gl.canvas.width-200).onChange(function(e) {
translate[0] = e;
drawScene(gl, program);
});
gui.add(guiField, 'y', 0, gl.canvas.height-200).onChange(function(e) {
translate[1] = e;
drawScene(gl, program);
});
let ui = document.getElementById('ui');
ui.appendChild(gui.domElement);
}
设置矩形坐标:
function setRectangle(gl, x, y, width, height) {
let x1 = x, x2 = x + width;
let y1 = y, y2 = y + height;
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
x1, y1,
x2, y1,
x1, y2,
x1, y2,
x2, y1,
x2, y2
]), gl.STATIC_DRAW);
}
将画图封装为函数drawScene,同样接收gl,program为参数:
function drawScene(gl, program) {
webglUtils.resizeCanvasToDisplaySize(gl.canvas);
//告诉WebGL如何从剪辑空间转换为像素
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
//清除canvas
gl.clear(gl.COLOR_BUFFER_BIT);
//应用着色器程序
gl.useProgram(program);
//开启顶点属性
gl.enableVertexAttribArray(program.pLocation);
//绑定缓冲区
gl.bindBuffer(gl.ARRAY_BUFFER, program.pBuffer);
setRectangle(gl, translate[0], translate[1], width, height);
//获取缓冲区数据
gl.vertexAttribPointer(program.pLocation, 2, gl.FLOAT, false, 0, 0);
//设置分辨率
gl.uniform2f(program.rLocation, gl.canvas.width, gl.canvas.height);
//设置颜色
gl.uniform4fv(program.cLocation, color);
gl.drawArrays(gl.TRIANGLES, 0, 6);
}
完整示例:
!DOCTYPE html>
平移
下一节,笔者将带大家一起实现用WebGL写字的骚操作。敬请期待!