Skip to content

在三维世界中,三角形具有重要的作用。构成三维模型的基本单位就是三角形,任何复杂三维模型都可以用三角形构成。

本章知识点主要包括:

  • webgl绘制多个点
  • webgl绘制三角形
  • 缓冲区对象如何使用
  • 类型化数组
  • 旋转、缩放、平移矩阵

绘制多个点

javascript
/**
 * Created by hushhw on 17/12/13.
 */
//MultiPoints.js
//顶点着色器程序
var VSHADER_SOURCE =
    'attribute vec4 a_Position;'+
    'void main(){'+
    'gl_Position=a_Position;'+
    'gl_PointSize=10.0;'+
    '}';

//片元着色器程序
var FSHADER_SOURCE=
    'void main(){'+
    'gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);'+
    '}';

function main() {
    //获取canvas元素
    var canvas = document.getElementById("webgl");
    if(!canvas){
        console.log("Failed to retrieve the <canvas> element");
        return;
    }

    //获取WebGL绘图上下文
    var gl = getWebGLContext(canvas);
    if(!gl){
        console.log("Failed to get the rendering context for WebGL");
        return;
    }

    //初始化着色器
    if(!initShaders(gl,VSHADER_SOURCE,FSHADER_SOURCE)){
        console.log("Failed to initialize shaders.");
        return;
    }

    //设置顶点位置
    var n = initVertexBuffers(gl);
    if (n < 0) {
        console.log('Failed to set the positions of the vertices');
        return;
    }


    //指定清空<canvas>颜色
    gl.clearColor(0.0, 0.0, 0.0, 1.0);

    //清空<canvas>
    gl.clear(gl.COLOR_BUFFER_BIT);

    //绘制三个点
    gl.drawArrays(gl.POINTS, 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("Failed to create thie buffer object");
        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');
    if(a_Position < 0){
        console.log("Failed to get the storage location of a_Position");
        return -1;
    }

    //将缓冲区对象分配给a_Postion变量
    gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);

    //连接a_Postion变量与分配给它的缓冲区对象
    gl.enableVertexAttribArray(a_Position);

    return n;
}

效果: 绘制多个点效果

如何使用缓冲区对象

上述代码中initVertexBuffers方法使用了缓冲区对象,让我们一起看看吧

缓冲区对象是WebGL系统中一个重要的内容,它是WebGL系统中的一块存储区域,我们可以一次性向缓冲区对象中填充大量的顶点数据,然后将这些数据保存在其中,供顶点着色器使用。

使用缓冲区对象的五个标准流程:

  1. 创建缓冲区对象 (gl.createBuffer())
  2. 绑定缓冲区对象(gl.bindBuffer())
  3. 将数据写入缓冲区对象(gl.bufferData())
  4. 将缓冲区对象分配给一个attribute变量(gl.vertexAttribPointer())
  5. 开启attribute变量(gl.enableVertexAttribArray())

使用缓冲区对象的五个流程 执行上述五个步骤的代码示例代码如下:

javascript
   //一、创建缓冲区对象
    var vertexBuffer = gl.createBuffer();
    if(!vertexBuffer){
        console.log("Failed to create thie buffer object");
        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_Postion变量
    gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);

    //五、开启attribute变量,连接a_Postion变量与分配给它的缓冲区对象
    gl.enableVertexAttribArray(a_Position);

第一步 创建缓冲区对象

WebGLRenderingContext.createBuffer() 方法可创建并初始化一个用于储存顶点数据或着色数据的WebGLBuffer对象 createBuffer执行前后的变化

第二步 绑定缓冲区对象

gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); WebGLRenderingContext.bindBuffer()方法将给定的WebGLBuffer绑定到目标。 bindBuffer()的语法: image.png 缓冲区对象绑定到目标上后,webgl系统内部状态如下: image.png

第三步 开辟空间并向缓冲区写入数据

gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

将第2个参数vervices中的数据写入到绑定到第一个参数gl.ARRAY_BUFFER上的缓冲区对象。 gl.bufferData()的语法如下: image.png 该方法执行后,WebGL系统的内部状态如下: image.png

第四步 将缓冲区对象分配给attribute变量

gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, _false_, 0, 0);gl.vertexAttribPointer()方法可以将整个缓冲区对象的引用分配给attribute变量。 image.png 该方法执行后,WebGL内部状态如下: image.png

第五步 开启分配了缓冲区的attribute变量

gl.enableVertexAttribArray(a_Position); 为了使得顶点着色器能够访问缓冲区内的数据,需要使用gl.enableVertexAttribArray() 开启attribute变量。 image.pngimage.png

gl.drawArrays()

image.png

移动、旋转和缩放

平移

image.png 要实现上述所示的平移操作,我们只需要将平移距离TX、TY、TZ的值,分别加在顶点坐标的对应分量上就可以。

todo 旋转