5.缓冲区

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;
}

 

你可能感兴趣的:(WebGL,javascript,webgl,canvas)