WebGL绘图
基本的几何图元有:三角形、线和点精灵,3D模型都是通过这些几何图元组成的。WebGL中有两个绘制图元的方法:
gl.drawArrays()
和gl.drawElements()
图元
三角形
WebGL中绘制三角形有三种方式:
gl.TRINGLES(独立三角形)
、gl.TRINGLE_STRIP(三角形带)
、glTRINGLE_FAN(三角形扇)
。对于一系列点
(v0、v1、v2、......)
,独立的三角形每三个点组成一个三角形((v0,v1,v2)、(v2,v3,v4)、......)
;三角形带每次将当前三角形的后面两个顶点与下一个顶点组成三角形((v0,v1,v2)、(v1,v2,v3)、......)
;三角形扇除掉第一个顶点,后面的每两个顶点与第一个顶点组成三角形((v0,v1,v2)、(v0,v3,v4)、......)
。线
WebGL中绘制线有三种方式:
gl.LINES(独立线)
、gl.LINE_STRIP(线带)
、gl.LINE_LOOP(线环)
。对于一系列点
(v0、v1、v2、......)
,独立线每两个点组成一条线((v0,v1)、(v2,v3)、......)
;线带每次将当前线的后面一个顶点与下一个顶点组成三角形((v0,v1)、(v1,v2)、......)
;线环与线带类似,线环最后一个顶点与第一个顶点相连。点精灵
点精灵就只有一种类型:
gl.POINTS
。可以在顶点着色器中使用内置变量gl_PointSize
设置点精灵的大小。
WebGL绘图方法
drawArrays()
void drawArrays(GLenum mode, GLint first, GLsizei count);
- mode定义了所要渲染的图元类型
- first定义数组的那个索引作为渲染的第一个索引
- count定义需要使用的顶点数
drawElements
void drawElements(GLenum mode, GLsizei count, GLenum type, GLintptr offset);
- mode定义所要渲染的图元类型
- count定义了绑定到
gl.ELEMENT_ARRAY_BUFFER
目标上的索引数 - type定义了元素索引的类型,可指定的类型有
gl.UNSIGNED_BYTE
和gl.UNSIGNED_SHORT
- offset定义绑定到
gl.ELEMENT_ARRAY_BUFFER
目标的缓冲中的偏移量,索引从此处开始
退化三角形
退化三角形是指三角形中至少有两个索引是相同的,因此退化三角形的面积为0.在绘制三角形带时,若多个三角形带之间存在不连续性,可以采用退化三角形的方式,添加额外的索引来保持三角形带的连续性。例如(v0,v1,v2)与(v3,v4,v5)不连续,可以在中间插入两个索引(v2,v3),从而构造四个退化三角形(v1,v2,v2)、(v2,v2,v3)、(v2、v3、v3)、(v3、v3、v4)。退化三角形会被GPU检测并删除。
类型化数组
Js中没有内置的二进制处理的功能,为了处理二进制数据,将二进制数据保持在长度固定的数组缓冲中
var buffer = new ArrayBuffer(8);
这样就得到一个8字节的缓冲。但无法直接对缓冲中数据进行处理,需要创建对应的视图。
var viewFloat32 = new Float32Array(buffer);
var viewUint16 = new Uint16Array(buffer);
分别创建了一个Float32
的视图和Uint16
格式的视图。Float32
占4个字节,所以viewFloat32
数组长度为2,数组的索引分别对应buffer
的前4个字节区域和后四个字节区域。viewUint16
数组的索引对应区域分割方法一致。
交叉存放顶点数据
顶点可能含有多种数据,例如位置、颜色等。对于致谢不同类型的数据,可以通过两种方式处理:
- 把每类数据放到不同的WebGLBuffer中,被称为数组结构。
- 把所有数据都放在一个WebGLBuffer中,被称为结构数组(交叉顶点数组)。
数组结构的使用:
例如要存储顶点的位置信息和颜色信息,则缓冲数组的格式为
顶点1 | 顶点2 | 顶点3 | … |
---|---|---|---|
(x,y,z,r,g,b,a) | (x,y,z,r,g,b,a) | (x,y,z,r,g,b,a) | … |
首先计算一个顶点占多少个字节:3*4+4*1=16
。为顶点分配空间并创建颜色和位置的视图
var buffer = new ArrayBuffer(16*count); // 每个顶点占字节数*顶点数
var positionView = new Float32Array(buffer);
var colorView = new Uint8Array(buffer);
写数据的时候通过视图写数据
var i,k;
var positionInFloats = 0; // 按照Float32格式划分缓冲的索引
var positionInBytes = 12; // 按照Uint8格式划分缓冲的索引
for(i=0,k=0;i<count;i++){
positionView[0+positionInFloats] = data[k++];
positionView[1+positionInFloats] = data[k++];
positionView[3+positionInFloats] = data[k++];
colorView[0+positionInBytes] = data[k++];
colorView[1+positionInBytes] = data[k++];
colorView[2+positionInBytes] = data[k++];
colorView[3+positionInBytes] = data[k++];
positionInFloats += 4;
positionInBytes += 16;
}
绑定缓冲数据
var vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, buffer, gl.STATIC_DRAW);
来源:CSDN
作者:Someu
链接:https://blog.csdn.net/Qimingweikun/article/details/80149788