绘图
WebGL只能绘制三种形状:
- 点
- 线
- 三角
其它的形状都是由上面的三种形状合成之后绘制到三维空间中的
执行绘图操作 WebGL 提供了两种方法:
- gl.drawElements()
- gl.drawArrays()
这两个方法的第一个参数都是一个常量
常量的取值范围如下:
- gl.POINTS: 将每个顶点当成一个点来绘制
- gl.LINES: 将数组当成一系列的顶点,在这些顶点间划线,每个顶点既是起点也是终点,因此数组中必须包含偶数个顶点才能完成绘制
- gl.LINE_LOOP: 将数组当成一系列顶点,在顶点间划线,从第一个点到第二个点,再从第二个点到第三个点,最后从最后一个点到第一个点
- gl.LINE_STRIP: 与LINE_LOOP相同,只不过不会绘制从最后一个点到第一个点的线
- gl.TRIANGLES: 将数组当成一系列顶点,在顶点间绘制三角形,除非明确规定否则每个三角形都单独绘制,不与其它三角形共享顶点
- gl.TRIANGLES_STRIP: 与上一个相比绘制三角形时会取前两个点与新的点构成新的三角形,即如果有 ABCD 四个点 第一次绘制三角形 ABC 第二次绘制三角形 BCD
- gl.TRIANGLES_FAN : 与上一个的区别在于如果有 ABCD 四个点 第一个绘制 ABC 然后绘制 ACD
此外,gl.drawElement() 还接收两个参数
- 数组缓冲区起始索引
- 缓冲区中的顶点个数
例如绘制三角形可以使用以下代码
// 已经完成了使用着色器清理窗口等初始化操作,具体操作参考前面的文章 // 定义三个顶点的坐标 let vertices = new Float32Array([0,1,1,-1,-1,-1]), buffer = gl.createBuffer(), vertexSetSize = 2, vertexSetCount = vertices.length/vertexSetSize, uColor, aVertexPosition; // 将数据放到缓冲区 gl.bindBuffer(gl.ARRAY_BUFFER, buffer); gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW); // 为片段着色器传入颜色值 uColor = gl.getUniformLocation(program, "uColor"); gl.uniform4fv(uColor, [0, 0, 0, 1]); // 为着色器传入顶点信息 aVertexPosition = gl.getAttribLocation(program, "aVertexPosition"); gl.enableVertexAttribArray(aVertexPosition); gl.vertexAttribPointer(aVertexPosition, vertexSetSize, gl.FLOAT, false, 0, 0); // 绘制 gl.drawArrays(gl.TRIANGLES, 0, vertexSetCount);
纹理
WebGL 的纹理可以使用DOM中的图像,创建纹理需要调用 gl.createTexture()
图像加载完成前,纹理不会初始化,所以最好在load事件后设置纹理
let image = new Image(), texture; image.src = "smile.gif"; image.onload = function(){ texture = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D,texture); gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); gl.texImage2D(gl.TEXTURE_2D,0,gl.RGBA, gl.UNSIGNED_BYTE, image); gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER, gl.NEAREST); gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.NEAREST); // 清除纹理 gl.bindTexture(gl.TEXTURE_2D,null); }
读取像素
WebGL读取像素需要使用 readPixels()
参数:
- x坐标
- y坐标
- 宽度
- 高度
- 图像格式
- 数据类型
- 类型化数组
示例:
let pixels = new Uint8Array(25*25); gl.readPixels(0, 0, 25, 25, gl.RGBA, gl.UNSIGNED_BYTE, pixels);