1. 程式人生 > >JavaScript-WebGL2學習筆記

JavaScript-WebGL2學習筆記

在前一篇WebGL的基礎上修改了程式碼,使之符合WebGL2規範。

<html>
<head>
    <!--
        Date: 2018-3-16
        Author: kagula
        Prologue:
        WebGL2的例子
        Prologue:

        Description:
        網上太多WebGL資料,為了避免混餚,我們在原本WebGL的基礎上瞭解WebGL2, 這裡還是用兩個三角形拼出一個彩色的正方形.

        Original:
        [1]https://my.oschina.net/thesadabc/blog/1592866

        測試環境
        [1]Chrome 65.0.3325.162
        [2]nginx  1.12.2
    -->
    <title>第一個Webgl2程式</title>

    <meta charset="utf-8">
    <!-- gl-matrix version 2.4.0 from http://glmatrix.net/ -->
    <script type="text/javascript" src="/gl-matrix-min.js"></script>

    <script type="text/javascript" src="/kagula/webgl_helper.js"></script>
</head>

<body>
    <canvas id="glCanvas" width="640" height="480"></canvas>
</body>

</html>

<script>
    main();

    //弄4個頂點, 4個顔色, 用來演示render流程!
    function initBuffers(gl) {
        // Create a buffer for the square's positions.
        const positionBuffer = gl.createBuffer();

        // Select the positionBuffer as the one to apply buffer
        // operations to from here out.
        gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);

        // Now create an array of positions for the square.
        const positions = [
           1.0, 1.0,
          -1.0, 1.0,
           1.0, -1.0,
          -1.0, -1.0,
        ];

        // Now pass the list of positions into WebGL to build the
        // shape. We do this by creating a Float32Array from the
        // JavaScript array, then use it to fill the current buffer.
        gl.bufferData(gl.ARRAY_BUFFER,
                      new Float32Array(positions),
                      gl.STATIC_DRAW);

        //給每個頂點弄一個顔色
        const colors = [
        1.0, 1.0, 1.0, 1.0,    // white
        1.0, 0.0, 0.0, 1.0,    // red
        0.0, 1.0, 0.0, 1.0,    // green
        0.0, 0.0, 1.0, 1.0,    // blue
        ];

        const colorBuffer = gl.createBuffer();//建立gl快取,但是不指定快取型別.
        gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);//指定olorBuffer的型別為gl.ARRAY_BUFFER
        //緩衝區物件中的資料只指定1次,但是常常使用。這種模式下,OpenGL會將資料放在能夠快速渲染的地方。
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);

        return {
            position: positionBuffer,
            color: colorBuffer,
        };
    }
    
    function main() {
        //選擇器的使用
        //http://www.runoob.com/jsref/met-document-queryselector.html
        const canvas = document.querySelector("#glCanvas");

        // Initialize the GL context
        //為了獲取WebGL2上下文,getContext方法傳入的引數是"webgl2",而不是"webgl".
        const gl = canvas.getContext("webgl2");

        // Only continue if WebGL is available and working
        if (!gl) {
            alert("Unable to initialize WebGL. Your browser or machine may not support it.");
            return;
        }

        //OpenGL ES 3.0 不支援多維陣列
        //對傳入的陣列大小有限制
        console.log("gl.MAX_VERTEX_UNIFORM_VECTORS=" + gl.MAX_VERTEX_UNIFORM_VECTORS + ", gl.MAX_FRAGMENT_UNIFORM_VECTORS=" + gl.MAX_FRAGMENT_UNIFORM_VECTORS);

        // Vertex shader program
        //WebGL2的著色器語言支援原本WebGL1的GLSL 100 ,同時也支援GLSL 300 es
        //要使用GLSL 300 es,需要在著色器程式碼中顯示宣告
        //版本宣告的程式碼需要在頂點著色器和片元著色器中同時指定, 版本宣告的程式碼必須嚴格在第一行.   
        //在webgl 1.0中 attribute表示輸入,varying表示輸入輸出.
        //現在要改為用/in out標記輸入,輸出.
        const vsSource = `#version 300 es
        in vec4 aVertexPosition;
        in vec4 aVertexColor;//從外部拿到顏色,不做任何處理,丟給vColor.

        uniform mat4 uModelViewMatrix;
        uniform mat4 uProjectionMatrix;

        //從aVertexColor拿到的顏色直接給vColor,
        //由vColor傳給Fragment Shader.
        out lowp vec4 vColor;

        void main() {
          gl_Position = uProjectionMatrix * uModelViewMatrix * aVertexPosition;
          vColor = aVertexColor;//什麼都不做,只是為了把從外部得到的color傳遞給Fragment Shader.
        }
        `;

        // Fragment shader, 相當於pixel shader  
        //varying被in代替
        //在GLSL 100 中,我們通過給內建變數gl_FragColor賦值來設定片元的輸出顏色
        //而在GLSL 300 es中,需要自己定義一個輸出顏色的變數,並在main函式中設定顏色值
        const fsSource = `#version 300 es
        precision highp float;//必須要為float型別指定精度                              
        in lowp vec4 vColor;//從vertex shader得到的顏色放在這裡。
        out vec4 myOutputColor;
        void main() {
          myOutputColor = vColor;
        }
        `;

        //裝配shader到shaderProgram中去
        const shaderProgram = initShaderProgram(gl, vsSource, fsSource);

        //為了讓外部的資料能統一傳到shanderProgram中去,新建programInfo物件。
        //vertexPosition => aVertexPosition位置
        //projectionMatrix => uProjectionMatrix位置
        //modelViewMatrix => uModelViewMatrix位置
        //...
        const programInfo = {
            program: shaderProgram,
            attribLocations: {
                vertexPosition: gl.getAttribLocation(shaderProgram, 'aVertexPosition'),
                vertexColor: gl.getAttribLocation(shaderProgram, 'aVertexColor'),
            },
            uniformLocations: {
                projectionMatrix: gl.getUniformLocation(shaderProgram, 'uProjectionMatrix'),
                modelViewMatrix: gl.getUniformLocation(shaderProgram, 'uModelViewMatrix'),
            },
        };

        //initBuffers(gl)返回要render的vertex.
        drawScene(gl, programInfo, initBuffers(gl));
    }//main
</script>