WebGL入門教程(二)-webgl繪製三角形

前面已經介紹過了webgl,WebGL入門教程(一)-初識webgl(http://www.cnblogs.com/bsman/p/6128447.html),也知道了如何繪製一個點,接下來就用webgl畫出一個三角形。javascript

效果圖:css

 

WebGL入門教程(一)-初識webgl中,知道如何繪製一個點html

//繪製一個點
gl.drawArrays(gl.POINTS, 0, 1);

可是圖形是有多個點組成,那麼就應該考慮如何繪製多個點,WebGL提供了一種很方便的機制,緩衝區對象(buffer object),它是WebGL系統中的一塊內存區域,它能夠一次性向着色器傳入多個頂點的數據,而後將這些數據保存在其中,供頂點着色器使用。java

首先先找到三個點,操做步驟:web

  1.建立HTML5 canvascanvas

  2.獲取畫布 canvas 的 ID數組

  3.獲取WebGL緩存

  4.編譯着色器post

  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;

}
相關文章
相關標籤/搜索