什么是缓冲区对象?
普通方式一次只能向顶点着色器写入一个点,而缓冲区对象可以向着色器一次性传入多个顶点数据,从而快速创建几何图形,如三角形、矩形、立方体等。它是WebGL系统中的一块内存区域,可以填充大量的顶点数据,保存在其中,供顶点着色器使用。
方法:
-
#.createBuffer()
创建缓冲区对象。
返回值 : 非null,新创建的建缓冲区对象;
null,创建缓冲区对象失败。
错误: 无 -
#.deleteBuffer(buffer)
删除参数buffer表示的缓冲区对象。
参数: buffer,待删除的缓冲区对象
返回值: 无
错误: 无 -
#.bindBuffer(target,buffer)
允许使用buffer表示的缓冲区对象并将其绑定到target表示的目标上。
参数: target参数可以是以下中的一个:
①gl.ARRAY_BUFFER,表示缓冲区对象包含了顶点的数据;
②gl.ELEMENT_ARRAY_BUFFER,表示缓冲区对象包含了顶点的索引值;
buffer,指定之前由gl.createBuffer()返回的待绑定的缓冲区对象
返回值: 无
错误: INVALID_ENUM,target不是上述值之一,这时将保持原有的绑定情况不变 -
#.bufferData(target,data,usage)
开辟存储空间,向绑定在target上的缓冲区对象中写入数据data。
参数: target gl.ARRAY_BUFFER或gl.ELEMENT_ARRAY_BUFFER
data,写入缓冲区对象的数据(类型化数组)
usage,表示程序将如何使用存储在缓冲区对象中的数据。
该参数将帮助WebGL优化操作,但是就算传入错误的值,也不会终止程序,仅仅是降低程序的效率:
①gl.STATIC_DRAW,只会想缓冲区对象写入一次数据,但需要绘制很多次
②gl.STREAM_DRAW,只会向缓冲区对象写入一次数据,然后绘制若干次
③gl.DYNAMIC_DRAW,会向缓冲区对象多次写入数据,并绘制很多次
返回值: 无
错误: INVALID_ENUM,target不是上述值之一,这时将保持原有的绑定情况不变 -
#.vertexAttribPointer(location,size,type,normalized,stride,offset)
将绑定到gl.ARRAY_BUFFER的缓冲区对象分配给由location指定的attribute变量
参数 | location | 指定待分配attribute变量的存储位置 |
---|---|---|
size | 指定缓冲区中每个顶点的分量个数(1-4),若size比attribute变量需要的分量数小,缺失分量将按照与gl.vertexAttrib[1234]f()相同的规则补全。比如,size为1,那么第2,3分量自动设为0,第4分量为1 | |
type | 用以下类型之一来指定数据类型: ①gl.UNSIGNED_BYTE,无符号字节,Uint8Array; ②gl.SHORT,短整型,Int16Array; ③gl.UNSIGNED_SHORT,无符号短整型,Uint16Array; ④gl.INT,整型,Int32Array; ⑤gl.UNSIGNED_INT,无符号整型,Uint32Array; ⑥gl.FLOAT,浮点型,Float32Array; | |
normalize | 传入true或false,表明是否将非浮点型的数据归一化到[0,1]或[-1,1]区间 | |
stride | 指定相邻两个顶点间的字节数,默认为0 | |
offset | 指定缓冲区对象中的偏移量(以字节为单位),即attribute变量从缓冲区中的何处开始存储,如果是从其实位置开始的,offset设为0 | |
返回值 | 无 | |
错误 | INVALID_OPERATION | 不存在当前程序对象 |
INVALID_VALUE | location大于等于attribute变量的最大数目(默认为8),或者stride或offset为负值 |
-
#.enableVertexAttribArray(location)
开启location指定的attribute变量
参数: location,指定attribute变量的存储位置
返回值: 无
错误: INVALID_VALUE,location大于等于attribute变量的最大数目(默认为8) -
#.disableVertexAttribArray(location)
关闭location指定的attribute变量
参数: location,指定attribute变量的存储位置
返回值: 无
错误: INVALID_VALUE,location大于等于attribute变量的最大数目(默认为8)
类型化数组
在绘制三维图形时,WebGL会处理大量相同类型的数据,例如顶点的坐标和颜色等数据。为了优化性能,WebGL为每种基本数据类型引入了一种特殊的数组,即类型化数组。
数组名 | 每个元素所占字节数 | 描述 |
---|---|---|
Int8Array | 1 | 8位整型数(signed char) |
UInt8Array | 1 | 8位无符号整型数(unsigned char) |
Int16Array | 2 | 16位整型数(signed short) |
UInt16Array | 2 | 16位无符号整型数(usigned short) |
Int32Array | 4 | 32位整型数(signed int) |
Uint32Array | 4 | 32位无符号整型数(usigned int) |
Float32Array | 4 | 单精度32位浮点数(float) |
Float64Array | 8 | 双精度64位浮点数(double) |
类型化数组不支持push()和pop()方法。
方法:
- #.get(index)
获取第index个元素值 - #.set(index,value)
设置第index个元素的值为value - #.set(array,offset)
从第offset个元素开始将数组array中的值填充进去
属性:
#.length
数组的长度
常量:
#.BYTES_PER_ELEMENT
元素中每个元素所占的字节数
初始化数组:
var vertices = new Float32Array(4);//直接声明数组元素个数
var vertices=new Float32Array([0.0,0.5,-0.5,-0.5,0.5,-0.5]);//直接给数组赋值
例子:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>缓冲区对象和类型化数组</title>
<script type="text/javascript" src="js/lib/webgl-debug.js" ></script>
<script type="text/javascript" src="js/lib/webgl-utils.js" ></script>
<script type="text/javascript" src="js/lib/cuon-utils.js" ></script>
</head>
<body>
<canvas id='canvas' width="600" height="600">该浏览器不支持WebGL!</canvas>
<script id="vertexShader" type="x-shader/x-vertex">
attribute vec4 a_Position;
void main(){
gl_Position=a_Position;
gl_PointSize=5.0;
}
</script>
<script id="fragmentShader" type="x-shader/x-fragment">
void main(){
gl_FragColor=vec4(1.0,0.0,0.0,1.0);
}
</script>
<script>
(function main(){
var canvas=document.getElementById("canvas");
var vShader=document.getElementById("vertexShader").textContent;
var fShader=document.getElementById("fragmentShader").textContent;
var gl=getWebGLContext(canvas);
if(!gl){
console.log("该浏览器不支持WebGL!");
return ;
}
if(!initShaders(gl,vShader,fShader)){
console.log('初始化着色器失败!');
return ;
}
//初始化顶点缓冲区,设置顶点位置
var n=initVertexBuffer(gl);
if(n<0){
console.log('无法获取顶点相关信息!');
return ;
}
gl.clearColor(0.0,0.0,0.0,1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.POINTS,0,n);
}());
function initVertexBuffer(gl){
var vertices=new Float32Array([0.0,0.5,-0.5,-0.5,0.5,-0.5])
var n=3;//顶点数
//创建缓冲区对象
var vertexBuffer=gl.createBuffer();
if(!vertexBuffer){
console.log("缓冲区创建失败!");
return -1;
}
//将缓冲区对象绑定到目标
gl.bindBuffer(gl.ARRAY_BUFFER,vertexBuffer);
//向缓冲区对象写入数据
gl.bufferData(gl.ARRAY_BUFFER,vertices,gl.STATIC_DRAW);
//获取attribute变量的存储位置
var a_Position=gl.getAttribLocation(gl.program,'a_Position');
if(a_Position<0){
console.log('无法获取变量的存储位置!');
return ;
}
//将缓冲区对象分配给a_Position变量
gl.vertexAttribPointer(a_Position,2,gl.FLOAT,false,0,0);
//将链接a_Position的变量分配给它的缓冲区对象
gl.enableVertexAttribArray(a_Position);
return n;
}
</script>
</body>
</html>