本专栏所有文章示例代码均可在我的gitee码云上获取,读者可自行下载:https://gitee.com/babyogl/learnWebGL;本节代码在文件夹chapter-02里面的color-triangle-02.html。
上节课笔者绘制了一个颜色随顶点位置变化的三角形,实现平移、旋转和缩放变换的矩阵计算,并提供了一个可供交互的菜单栏工具:原生webgl学习(三) WebGL中的矩阵运算:平移、旋转和缩放;
在前面我们已经画了两次三角形了,这次,改变一些套路,我们画矩形。画矩形的代码跟上一节大同小异,代码解释可以参考上一节:原生webgl学习(三) WebGL中的矩阵运算:平移、旋转和缩放,唯一不同的是顶点坐标发生了改变,利用两个三角形构成一个矩形,只需要将代码中的顶点稍作修改即可:
let positions = [
-150, -100,
150, -100,
-150, 100,
150, -100,
-150, 100,
150, 100
];
在画图的时候gl.drawArrays的参数稍作修改即可,由于顶点数组长度增加,由原来的3个顶点变为6个顶点,故count应变为6,在这里提供一种更加友好的方法,可以根据数组的长度画图:
//这样一来对所有数组都适用,三维的为positions.length / 3
let primitiveType = gl.TRIANGLES;
let offset3 = 0;
let count = positions.length / 2;
gl.drawArrays(primitiveType, offset3, count);//画图
这个demo的代码在你们下载的文件夹下的chapter-02里面的color-triangle-02.html,运行效果如下:
大家要注意,这个demo的矩形的颜色并不会随着顶点的位置的变化而变化,那是由于在JavaScript代码里面,已经提前设置好顶点的颜色,所以着色器代码也要稍微修改一下:
顶点着色器里面定义了一个用于接收来自JavaScript代码颜色信息的attribute变量:a_color,在JavaScript代码中,需要获取到这个变量的位置:
let colorAttributeLocation = gl.getAttribLocation(program, 'a_color');
为其创建缓冲区,并写入数据:
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
setColor(gl, 1);
//设置颜色,alpha为透明度
function setColor(gl, alpha = 1) {
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
Math.random(), Math.random(), Math.random(), alpha,
Math.random(), Math.random(), Math.random(), alpha,
Math.random(), Math.random(), Math.random(), alpha,
Math.random(), Math.random(), Math.random(), alpha,
Math.random(), Math.random(), Math.random(), alpha,
Math.random(), Math.random(), Math.random(), alpha
]), gl.STATIC_DRAW);
}
接下来要建立着色器中的a_color与上述缓冲区之间的链接,并取出缓冲区的数据:
//建立着色器中attribute颜色变量与缓冲区之间的连接
gl.enableVertexAttribArray(colorAttributeLocation);
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
const size2 = 4;//2维坐标:每次迭代运行提取两个单位数据
const type2 = gl.FLOAT;//每个单位的数据类型是32位浮点型;如果为Uint8Array的8位数组,要设置为gl.UNSIGNED_BYTE
const normalize2 = false;//不需要归一化数据
const stride2 = 0;//每次迭代前进大小* sizeof(类型)以获得下一个位置
const offset2 = 0;//从缓冲起始位置开始读取
//到指定的缓冲区取出数据
gl.vertexAttribPointer(colorAttributeLocation, size2, type2, normalize2, stride2, offset2);
更多的细节请读者自行看代码,里面有详细的注释。这里有一个问题,我们要画矩形和干嘛,有什么用?这里笔者想到了一个比较有趣的应用,利用三角形和矩形构建中文简体字,在后面的文章将带领读者一起实现这个骚操作!但在这之前,还存在一个问题,笔者之前是为了更直观的向大家展示WebGL代码的使用方式,但那样看起来代码似乎很凌乱,用的代码量也很多,也不符合实际开发的要求,下一节,同样是实现一个矩形,但会将相关的功能封装,是代码看起来更加简洁易用。