1.缓冲区对象:缓冲区对象是WebGL系统中的一块内存区域,我们可以一次性向其中填充大量的顶点数据,供顶点着色器使用。
2.使用缓冲区对象步骤:
(1)创建缓冲区对象
//gl是canvas的上下文对象
var vertexBuffer = gl.createBuffer();
(2)绑定缓冲区对象
gl.bindBuffer(gl.ARRAY_BUFFER,vertexBuffer);
API:gl.bindBuffer( target,buffer ),允许使用buffer表示的缓冲区对象并将其绑定到target表示的目标上,target表示缓冲区对象的用途,这样WebGL才能正确处理其中的内容
target参数可以是以下中的任意一个:
gl.ARRAY_BUFFER:表示缓冲区对象中包含了顶点数据
gl.ELEMENT_ARRAY_BUFFER:表示缓冲区对象中包含了顶点的索引值
ARRAY_BUFFER:OpenGL ES着色器语言(GLSL ES)
buffer:指定之前由gl.createBuffer()返回的带绑定缓冲区对象
(3)将数据写入缓冲区对象,将第二个参数的数据写入绑定到target上的缓冲区对象。我们不能直接向缓冲区写入数据,只能向target写入数据,所以要想向缓冲区写入数据必先绑定
gl.bufferData(gl.ARRAY_BUFFER,vertices,gl.STATIC_DRAW);
API:gl.bufferData( target,data,usage)
target:gl.ARRAY_BUFFER或gl.ELEMENT_ARRAY_BUFFER
data:写入缓冲区对象的数据
usage:表示程序如何使用存储在缓冲区对象中的数据,该参数帮助WebGL优化操作,可取的值有:
gl.STATIC_DRAW,只向缓冲区对象写入一次数据,但需要绘制很多次;
gl.STREAM_DRAW,只向缓冲区对象写入一次数据,然后绘制很多次
gl.DYNAMIC_DRAW,只向缓冲区对象中多次写入数据,并绘制很多次
(4)将缓冲区对象分配给变量
gl.vertexAttribPointer(a_Position,2,gl.FLOAT,flase,0,0);
API:gl.vertexAttribPointer( location, size, type, normalized, stride, offset)
location:指定待分配attribute变量的存储位置
size:指定缓冲区中每个顶点的分量个数(1-4),若size比attribute变量需要的分量小,按默认规则补全
type:指定数据格式,可取值:gl.UNSIGEND_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变量是缓冲区何处开始存储
(5)开启变量,使顶点着色器能够访问缓冲区中的数据
gl.enableVertexAttribArray(location)
API:gl.enableVertexAttribArray(location)
location:指定attribute变量的存储位置
下面例子是画一个三角形:
var SHADER_SOURCE =
'attribute vec4 a_Position;\n'+
'void main(){\n'+
'gl_Position = a_Position;\n'+
'}\n';
var FSHADER_SOURCE =
'precision mediump float;\n'+
'uniform vec4 u_FragColor;\n'+
'void main(){\n'+
'gl_FragColor = u_FragColor;\n'+
'}\n';
function main()
{
var canvas = document.getElementById("webgl");
if(!canvas)
{
console.log("获取canvas标签失败");
}
var gl = canvas.getContext("webgl");
if(!gl)
{
console.log("获取上下文失败");
}
if(!initShaders(gl,SHADER_SOURCE,FSHADER_SOURCE))
{
console.log("加载着色器程序失败");
}
var n = initVertexBuffers(gl);
var u_FragColor = gl.getUniformLocation(gl.program,'u_FragColor');
gl.uniform4f(u_FragColor,1.0,0.0,0.0,1.0);
if(n<0)
{
console.log("设置顶点失败");
}
gl.drawArrays(gl.TRIANGLES,0,n);
}
function initVertexBuffers(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);
var a_Position = gl.getAttribLocation(gl.program,'a_Position');
//将缓冲区对象分配给a_Position变量
gl.vertexAttribPointer(a_Position,2,gl.FLOAT,false,0,0);
//连接a_Position变量与分配给他的缓冲区对象
gl.enableVertexAttribArray(a_Position);
return n;
}
点的位置和大小共用一个缓冲区:
var SHADER_SOURCE =
'attribute vec4 a_Position;\n'+
'attribute float a_PointSize;\n'+
'void main(){\n'+
'gl_Position = a_Position;\n'+
'gl_PointSize = a_PointSize;\n'+
'}\n';
var FSHADER_SOURCE =
'precision mediump float;\n'+
'uniform vec4 u_FragColor;\n'+
'void main(){\n'+
'gl_FragColor = u_FragColor;\n'+
'}\n';
function main()
{
var canvas = document.getElementById("webgl");
if(!canvas)
{
console.log("获取canvas标签失败");
}
var gl = canvas.getContext("webgl");
if(!gl)
{
console.log("获取上下文失败");
}
if(!initShaders(gl,SHADER_SOURCE,FSHADER_SOURCE))
{
console.log("加载着色器程序失败");
}
var n = initVertexBuffers(gl);
var u_FragColor = gl.getUniformLocation(gl.program,'u_FragColor');
gl.uniform4f(u_FragColor,1.0,0.0,0.0,1.0);
if(n<0)
{
console.log("设置顶点失败");
}
gl.drawArrays(gl.POINTS,0,n);
}
function initVertexBuffers(gl)
{
var vertices = new Float32Array([
0.0,0.5,10.0,
-0.5,-0.5,20.0,
0.5,-0.5,30.0
]);
var n = 3; //顶点个数
//创建缓冲区对象
var vertexBuffer = gl.createBuffer();
if(!vertexBuffer)
{
console.log("创建缓冲区失败");
return -1;
}
var FSIZE = vertices.BYTES_PER_ELEMENT;
//将缓冲区对象绑定到目标
gl.bindBuffer(gl.ARRAY_BUFFER,vertexBuffer);
//向缓冲区对象写入数据
gl.bufferData(gl.ARRAY_BUFFER,vertices,gl.STATIC_DRAW);
var a_Position = gl.getAttribLocation(gl.program,'a_Position');
//将缓冲区对象分配给a_Position变量
gl.vertexAttribPointer(a_Position,2,gl.FLOAT,false,FSIZE*3,0);
//连接a_Position变量与分配给他的缓冲区对象
gl.enableVertexAttribArray(a_Position);
var sizeBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,sizeBuffer);
gl.bufferData(gl.ARRAY_BUFFER,vertices,gl.STATIC_DRAW);
var a_PointSize = gl.getAttribLocation(gl.program,'a_PointSize');
gl.vertexAttribPointer(a_PointSize,1,gl.FLOAT,false,FSIZE*3,FSIZE*2);
gl.enableVertexAttribArray(a_PointSize);
return n;
}