• WebGL入门教程(二)-webgl绘制三角形


    前面已经介绍过了webgl,WebGL入门教程(一)-初识webgl(http://www.cnblogs.com/bsman/p/6128447.html),也知道了如何绘制一个点,接下来就用webgl画出一个三角形。

    效果图:

    WebGL入门教程(一)-初识webgl中,知道如何绘制一个点

    //绘制一个点
    gl.drawArrays(gl.POINTS, 0, 1);

    但是图形是有多个点组成,那么就应该考虑如何绘制多个点,WebGL提供了一种很方便的机制,缓冲区对象(buffer object),它是WebGL系统中的一块内存区域,它可以一次性向着色器传入多个顶点的数据,然后将这些数据保存在其中,供顶点着色器使用。

    首先先找到三个点,操作步骤:

      1.创建HTML5 canvas

      2.获取画布 canvas 的 ID

      3.获取WebGL

      4.编译着色器

      5.使用缓冲区对象向顶点传入多个顶点数据

      6.绘制图像

    以上1~4参考:http://www.cnblogs.com/bsman/p/6128447.html

     4.编译着色器

    修改顶点着色器,去掉gl_PointSize,这个只有绘制点的时候才有用

    //顶点着色器程序
        var VSHADER_SOURCE =
            "attribute vec4 a_Position;" +
            "void main() {" +
                //设置坐标
            "gl_Position = a_Position; " +
            "} ";

     5.使用缓冲区对象向顶点传入多个顶点数据又分为五步

     5.1创建缓冲区对象

     //创建缓冲区对象
      var vertexBuffer = gl.createBuffer();

     5.2绑定缓冲区对象

    //将缓冲区对象绑定到目标
     gl.bindBuffer(gl.ARRAY_BUFFER,vertexBuffer);

    其中gl.ARRAY_BUFFER表示缓冲区对象包含了顶点的数据,要是换成gl.ELEMENT_ARRAY_BUFFER则表示包含了顶点的索引;vertexBuffer表示上一步创建的缓存区对象。

     5.3将数据写入缓冲区对象

    //向缓冲区写入数据
    gl.bufferData(gl.ARRAY_BUFFER,vertices,gl.STATIC_DRAW);

    其中:gl.ARRAY_BUFFER表示目标;vertices表示写入缓存区对象的数据(类型化数组);第三个参数有3种(

    gl.STATIC_DRAW:表示只会向缓存区对象写入一次数据,但需要绘制很多次;
    gl.STREAM_DRAW:表示只会向缓存区对象写入一次数据,然后绘制若干次;
    gl.DYNAMIC_DRAW:表示会向缓存区对象多次写入数据,并绘制很多次;

    其中第二个参数,类型化数组是WEBGL为了优化性能引入的一种特殊的数组,该数组不支持push,pop有(

    Int8Array :8位整形数

    UInt8Array :8位无符号整形数

    Int16Array :16位整形数

    UInt8Array :16位无符号整形数

    Int32Array :32位整形数

    UInt8Array :32位无符号整形数

    Float32Array :单精度32位浮点数

    Float64Array :双精度64位浮点数

    )属性方法有get(index)、set(index,value)、set(array,offset)、length

    这种数组一定要new,否则报错,错误信息如下:

    GL ERROR :GL_INVALID_OPERATION :glDrawArrays: attempt to access out of range vertices in attribute 0

    例如:

    var vertices = new Float32Array([0.0, 0.5, -0.5, -0.5, 0.5, -0.5]);

     5.4将缓冲区对象分配给一个attribute变量

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

    第一个参数:指定待分配attribute变量的存储位置

    第二个参数:指定缓存区中每个顶点的分量个数(1~4)

    第三个参数:类型有,gl.UNSIGNED_BYTE无符号字节,gl.SHORT短整数,gl.UNSIGNED_SHORT无符号短整数,gl.INT整型,gl.UNSIGNED_INT无符号整型,gl.FLOAT浮点型。

    第四个参数:表示是否将非浮点型的数据归到[0,1][-1,1]区间

    第五个参数:相邻两个顶点的字节数。默认为0

    第六个参数:表示缓存区对象的偏移量(以字节为单位),就是attribute变量从缓冲区中的何处开始存储。

     5.5开启attribute变量

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

    就是开启attribute变量,是缓存区对attribute变量分配生效,使顶点着色器能够访问缓冲区内的数据。

      6.绘制图像

    WebGL可以绘制的图形有:
    gl.POINTS 一系列点,绘制v0,v1……。
    线段 gl.LINES 一系列单独的线段,绘制(v0,v1),(v2,v3)……如果是奇数,最后一个省略。
    线条 gl.LINE_STRIP 一系列连接的线段,绘制(v0,v1),(v1,v2),(v2,v3)……除了第一个和最后一个,其他的点点即是起点又是终点。
    回路 gl.LINE_LOOP 一系列连接的线段,绘制(v0,v1),(v1,v2),(v2,v3)……(vn,v0),最后一个点会连接起点。
    三角形 gl.TRIANGLES 一系列单独的三角形,绘制(v0,v1,v2),(v3,v4,v5)……如果不是3的倍数,剩下的将会被忽略。
    三角带 gl.TRIANGLES_STRIP 一系列连接的三角形,绘制(v0,v1,v2),(v2,v1,v3),(v2,v3,v4)……以此类推,第二个是(v2,v1,v3)而不是(v1,v2,v3)是为了保持绘制按照逆时针绘制
    gl.drawArrays(gl.TRIANGLES, 0, n);

    完整代码:

    html代码

    <!DOCTYPE html>
    <html>
    <head>
        <meta lang="en">
        <meta charset="UTF-8">
        <title>WebGL study</title>
        <link href="../ClickedPoints/style.css">
        <script type="text/javascript" src="../Triangle/js.js"></script>
    </head>
    <body>
    <canvas id="canvas" width="200px" height="200px"></canvas>
    </body>
    </html>

    javascript代码

    /**
     * Created by HBX on 2016/12/3.
     */
    window.onload = function () {
    
        //顶点着色器程序
        var VSHADER_SOURCE =
            "attribute vec4 a_Position;" +
            "void main() {" +
                //设置坐标
            "gl_Position = a_Position; " +
            "} ";
    
        //片元着色器
        var FSHADER_SOURCE =
            "void main() {" +
                //设置颜色
            "gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);" +
            "}";
        //获取canvas元素
        var canvas = document.getElementById('canvas');
        //获取绘制二维上下文
        var gl = canvas.getContext('webgl');
        if (!gl) {
            console.log("Failed");
            return;
        }
        //编译着色器
        var vertShader = gl.createShader(gl.VERTEX_SHADER);
        gl.shaderSource(vertShader, VSHADER_SOURCE);
        gl.compileShader(vertShader);
    
        var fragShader = gl.createShader(gl.FRAGMENT_SHADER);
        gl.shaderSource(fragShader, FSHADER_SOURCE);
        gl.compileShader(fragShader);
        //合并程序
        var shaderProgram = gl.createProgram();
        gl.attachShader(shaderProgram, vertShader);
        gl.attachShader(shaderProgram, fragShader);
        gl.linkProgram(shaderProgram);
        gl.useProgram(shaderProgram);
    
        //获取坐标点
        var a_Position = gl.getAttribLocation(shaderProgram, 'a_Position');
    
        if (a_Position < 0) {
            console.log('Failed to get the storage location of a_Position');
            return;
        }
    
        var n = initBuffers(gl,shaderProgram);
    
        if(n<0){
            console.log('Failed to set the positions');
            return;
        }
        // 清除指定<画布>的颜色
        gl.clearColor(0.0, 0.0, 0.0, 1.0);
    
        // 清空 <canvas>
        gl.clear(gl.COLOR_BUFFER_BIT);
    
        gl.drawArrays(gl.TRIANGLES, 0, n);
    }
    
    function initBuffers(gl,shaderProgram) {
        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 the butter object");
            return -1;
        }
         //将缓冲区对象绑定到目标
        gl.bindBuffer(gl.ARRAY_BUFFER,vertexBuffer);
        //向缓冲区写入数据
        gl.bufferData(gl.ARRAY_BUFFER,vertices,gl.STATIC_DRAW);
        //获取坐标点
        var a_Position = gl.getAttribLocation(shaderProgram, 'a_Position');
        //将缓冲区对象分配给a_Position变量
        gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);
        //连接a_Position变量与分配给它的缓冲区对象
        gl.enableVertexAttribArray(a_Position);
        return n;
    
    }
  • 相关阅读:
    正则笔记
    html5的选择器
    原生js操作dom备忘
    avalon使用笔记
    webpack2配置备份
    美女图片小爬虫,嘿嘿
    JS原型和继承
    localstorage sessionstorage cookie 备忘
    gulp配置文件备份
    node代码片段
  • 原文地址:https://www.cnblogs.com/bsman/p/6146343.html
Copyright © 2020-2023  润新知