天天看點

HTML5 WEBGL學習2 實時3D渲染

中文教程位址:

​​​http://www.hiwebgl.com/?p=42​​​

項目開源位址:

​​​https://github.com/tparisi/Programming3DApplications​​

WEB GL不屬于HTML5官方标準,但絕大多數支援HTML5的浏覽器都支援WebGL。

  • WebGL是一套底層繪圖API,它通過解析資料和着色器陣列來進行繪制。
  • WebGL基于OpenGL Es2.0,ES代表嵌入式系統。
  • WebGL可以與其它Web頁面元素相結合。
  • WebGL為建立動态Web應用而生
  • WebGL是跨平台的
  • WebGL是免費的。

WebGL應用剖析

為了在頁面中渲染WebGL,一個應用至少應當執行以下步驟:

  1. 建立一個Canvas元素
  2. 擷取Canvas元素中的繪圖上下文
  3. 初始化視口
  4. 建立一個或多個包含待渲染資料(通常是頂點資料)的緩沖
  5. 建立一個或多個定義頂點緩沖到螢幕空間轉換規則的矩陣
  6. 建立一個或多個實作繪制算法的着色器
  7. 使用各項參數初始化着色器
  8. 繪制

簡單的WebGL示例

HTML5 WEBGL學習2 實時3D渲染

1. 從Canvas獲得WebGL上下文

function initWebGL(canvas) {
        var gl = null;
        var msg = "Your browser does not support WebGL, " +
            "or it is not enabled by default.";
        try 
        {
            gl = canvas.getContext("experimental-webgl");
        } 
        catch (e)
        {
            msg = "Error creating WebGL Context!: " + e.toString();
        }

        if (!gl)
        {
            alert(msg);
            throw new Error(msg);
        }
        return gl;        
     }      

2. 視口

function initViewport(gl, canvas)
    {
        gl.viewport(0, 0, canvas.width, canvas.height);
    }      

3. 緩沖、緩沖數組和類型化數組

WebGL基于圖元(primitive)進行圖像繪制。圖元以數組的形式存儲資料,這個數組被稱為緩沖(buffer),待繪制的頂點資料在緩沖中被定義。

建立一個1*1正方形頂點緩沖:

function createSquare(gl) {
        var vertexBuffer;
        vertexBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
        var verts = [
             .5,  .5,  0.0,
            -.5,  .5,  0.0,
             .5, -.5,  0.0,
            -.5, -.5,  0.0
        ];
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(verts), gl.STATIC_DRAW);
        var square = {buffer:vertexBuffer, vertSize:3, nVerts:4, primtype:gl.TRIANGLE_STRIP};
        return square;
    }      

Float32Array,是一種浏覽器專門為WebGL引入的新資料類型。Float32Array是一類緩沖數組(ArrayBuffer),也稱為類型化數組(typed array)。它是一種以二進制方式存儲的JavaScript類型。

4. 矩陣

在繪制正方形前,首先要建立一對矩陣。一個矩陣用于定義正方形在3D坐标系統中的位置(相對于相機),這個矩陣被稱為模型-視圖矩陣,因為它同時包含模型矩陣和視圖矩陣的資訊。

第二個矩陣被稱為投影矩陣,着色器使用它來執行從3D空間坐标到2D視口繪制空間坐标的轉換。

var projectionMatrix, modelViewMatrix;
    function initMatrices(canvas)
    {
        // Create a model view matrix with object at 0, 0, -3.333
        modelViewMatrix = mat4.create();
        mat4.translate(modelViewMatrix, modelViewMatrix, [0, 0, -3.333]);
        // Create a project matrix with 45 degree field of view
        projectionMatrix = mat4.create();
        mat4.perspective(projectionMatrix, Math.PI / 4, canvas.width / canvas.height, 1, 10000);
    }      

5. 着色器

着色器是一段使用GLSL編寫的簡短程式。

function createShader(gl, str, type) {
        var shader;
        if (type == "fragment") {
            shader = gl.createShader(gl.FRAGMENT_SHADER);
        } else if (type == "vertex") {
            shader = gl.createShader(gl.VERTEX_SHADER);
        } else {
            return null;
        }
        gl.shaderSource(shader, str);
        gl.compileShader(shader);
        if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
            alert(gl.getShaderInfoLog(shader));
            return null;
        }
        return shader;
    }      

着色器代碼以JavaScript字元串的形式定義,存儲在全局變量中。

var vertexShaderSource =

        "    attribute vec3 vertexPos;\n" +
        "    uniform mat4 modelViewMatrix;\n" +
        "    uniform mat4 projectionMatrix;\n" +
        "    void main(void) {\n" +
        "       // Return the transformed and projected vertex value\n" +
        "        gl_Position = projectionMatrix * modelViewMatrix * \n" +
        "            vec4(vertexPos, 1.0);\n" +
        "    }\n";
    var fragmentShaderSource = 
        "    void main(void) {\n" +
        "    // Return the pixel color: always output white\n" +
        "    gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n" +
        "}\n";      

6. 繪制圖元

function draw(gl, obj) {
       // clear the background (with black)
       gl.clearColor(0.0, 0.0, 0.0, 1.0);
       gl.clear(gl.COLOR_BUFFER_BIT);
       // set the shader to use
       gl.useProgram(shaderProgram);
       // connect up the shader parameters: vertex position and projection/model matrices
       // set the vertex buffer to be drawn
       gl.bindBuffer(gl.ARRAY_BUFFER, obj.buffer);
       gl.vertexAttribPointer(shaderVertexPositionAttribute, obj.vertSize, gl.FLOAT, false, 0, 0);
       gl.uniformMatrix4fv(shaderProjectionMatrixUniform, false, projectionMatrix);
       gl.uniformMatrix4fv(shaderModelViewMatrixUniform, false, modelViewMatrix);
       // draw the object
       gl.drawArrays(obj.primtype, 0, obj.nVerts);
    }      

繼續閱讀