webgl 20.畫一個(gè)正方體

cube.png
coordiantes.png

要畫這個(gè)正方體每個(gè)面可以分成 2 個(gè)三角形醋安,這樣每個(gè)面需要 6 個(gè)頂點(diǎn),6個(gè)面總共需要 36 個(gè)頂點(diǎn)斩箫。如果用 gl.TRIANGLE_FAN 則每個(gè)面需要 4 個(gè)頂點(diǎn)里伯,6 個(gè)面總共需要 24 個(gè)頂點(diǎn)。這樣傳的頂點(diǎn)太多了崎弃,webgl 用索引(index) 解決這個(gè)問題甘晤,我們只需要傳 8 個(gè)頂點(diǎn)進(jìn)去含潘,然后引用頂點(diǎn)的索引值就可以了。

<script id="vertex-shader" type="glsl">
    attribute vec4 a_Position;
    attribute vec4 a_Color;
    uniform mat4 u_mvpMatrix;
    varying vec4 v_Color;

    void main() {
        gl_Position = u_mvpMatrix * a_Position;
        v_Color = a_Color;
    }
</script>

<script id="fragment-shader" type="glsl">
    precision mediump float;
    varying vec4 v_Color;
    void main() {
       gl_FragColor = v_Color;
    }
</script>

8個(gè)頂點(diǎn)及顏色

   //    v6----- v5
   //   /|      /|
   //  v1------v0|
   //  | |     | |
   //  | |v7---|-|v4
   //  |/      |/
   //  v2------v3
var vertices = new Float32Array([
   // Vertex coordinates and color
   1.0, 1.0, 1.0, 1.0, 1.0, 1.0,  // v0 White
   -1.0, 1.0, 1.0, 1.0, 0.0, 1.0,  // v1 Magenta
   -1.0, -1.0, 1.0, 1.0, 0.0, 0.0,  // v2 Red
   1.0, -1.0, 1.0, 1.0, 1.0, 0.0,  // v3 Yellow
   1.0, -1.0, -1.0, 0.0, 1.0, 0.0,  // v4 Green
   1.0, 1.0, -1.0, 0.0, 1.0, 1.0,  // v5 Cyan
   -1.0, 1.0, -1.0, 0.0, 0.0, 1.0,  // v6 Blue
   -1.0, -1.0, -1.0, 0.0, 0.0, 0.0   // v7 Black
]);

生成 index (索引)數(shù)組

var indices = new Uint8Array([
    0, 1, 2, 0, 2, 3,    // front
    0, 3, 4, 0, 4, 5,    // right
    0, 5, 6, 0, 6, 1,    // up
    1, 6, 7, 1, 7, 2,    // left
    7, 4, 3, 7, 3, 2,    // down
    4, 7, 6, 4, 6, 5     // back
]);

索引編號(hào) 0~7安皱,每個(gè)面還是用 6 個(gè)頂點(diǎn)畫 2 個(gè)三角形
索引的數(shù)據(jù)類型定義為了 Uint8调鬓,Uint8 取值范圍是 0~255 最多只能表示 256 個(gè)數(shù),如果索引的個(gè)數(shù)超過 256 就應(yīng)該使用范圍更大的數(shù)據(jù)類型酌伊。

創(chuàng)建 index buffer 并拷貝索引值到 GPU 中

var indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
gl.ELEMENT_ARRAY_BUFFER 表示數(shù)據(jù)是索引
gl.drawElements(gl.TRIANGLES, n, gl.UNSIGNED_BYTE, 0);
gl.drawElements 表示使用索引值來畫

第一個(gè)參數(shù)還是表示要畫的圖形
第二參數(shù)表示要畫的索引的個(gè)數(shù)
第三個(gè)參數(shù)表示索引值的類型腾窝,我們用了 Uint8,所以類型是 gl.UNSIGNED_BYTE
最后一個(gè)參數(shù)是 offset 表示起始偏移

完整代碼

<script id="vertex-shader" type="glsl">
    attribute vec4 a_Position;
    attribute vec4 a_Color;
    uniform mat4 u_mvpMatrix;
    varying vec4 v_Color;

    void main() {
        gl_Position = u_mvpMatrix * a_Position;
        v_Color = a_Color;
    }
</script>

<script id="fragment-shader" type="glsl">
    precision mediump float;
    varying vec4 v_Color;
    void main() {
       gl_FragColor = v_Color;
    }
</script>

<script src="lib/cuon-matrix.js"></script>
<script src="lib/myutils.js"></script>

<script>
    var VERTEX_SHADER_SOURCE = document.getElementById('vertex-shader').text;
    var FRAGMENT_SHADER_SOURCE = document.getElementById('fragment-shader').text;

    var canvas = document.getElementById("canvas");
    var gl = canvas.getContext('webgl');

    if (!initShaders(gl, VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE)) {
        alert('Failed to init shaders');
    }

    var n = initVertexBuffers(gl);

    var u_mvpMatrix = gl.getUniformLocation(gl.program, 'u_mvpMatrix');
    // <projection matrix> * <view matrix>
    var mvpMatrix = new Matrix4();
    mvpMatrix.setPerspective(30, 1, 1, 100);
    mvpMatrix.lookAt(3, 3, 7, 0, 0, 0, 0, 1, 0);

    gl.uniformMatrix4fv(u_mvpMatrix, false, mvpMatrix.elements);

    gl.enable(gl.DEPTH_TEST);
    gl.clearColor(0.0, 0.0, 0.0, 1.0);
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    gl.drawElements(gl.TRIANGLES, n, gl.UNSIGNED_BYTE, 0);

    function initVertexBuffers(gl) {
        // Create a cube
        //    v6----- v5
        //   /|      /|
        //  v1------v0|
        //  | |     | |
        //  | |v7---|-|v4
        //  |/      |/
        //  v2------v3

        var vertices = new Float32Array([
            // Vertex coordinates and color
            1.0, 1.0, 1.0, 1.0, 1.0, 1.0,  // v0 White
            -1.0, 1.0, 1.0, 1.0, 0.0, 1.0,  // v1 Magenta
            -1.0, -1.0, 1.0, 1.0, 0.0, 0.0,  // v2 Red
            1.0, -1.0, 1.0, 1.0, 1.0, 0.0,  // v3 Yellow
            1.0, -1.0, -1.0, 0.0, 1.0, 0.0,  // v4 Green
            1.0, 1.0, -1.0, 0.0, 1.0, 1.0,  // v5 Cyan
            -1.0, 1.0, -1.0, 0.0, 0.0, 1.0,  // v6 Blue
            -1.0, -1.0, -1.0, 0.0, 0.0, 0.0   // v7 Black
        ]);

        // index
        var indices = new Uint8Array([
            0, 1, 2, 0, 2, 3,    // front
            0, 3, 4, 0, 4, 5,    // right
            0, 5, 6, 0, 6, 1,    // up
            1, 6, 7, 1, 7, 2,    // left
            7, 4, 3, 7, 3, 2,    // down
            4, 7, 6, 4, 6, 5     // back
        ]);

        var vertexBuffer = gl.createBuffer();
        if (!vertexBuffer) {
            console.log('Failed to create buffer object');
            return -1;
        }
        gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
        gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

        var FSIZE = vertices.BYTES_PER_ELEMENT;

        var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
        gl.vertexAttribPointer(a_Position, 3, gl.FLOAT, false, 6 * FSIZE, 0);
        gl.enableVertexAttribArray(a_Position);

        var a_Color = gl.getAttribLocation(gl.program, 'a_Color');
        gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, 6 * FSIZE, 3 * FSIZE);
        gl.enableVertexAttribArray(a_Color);

        var indexBuffer = gl.createBuffer();
        if (!indexBuffer) {
            console.log('Failed to create index buffer');
            return -1;
        }
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
        gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);

        return indices.length;
    }
</script>

查看源碼

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末虹脯,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子奏候,更是在濱河造成了極大的恐慌循集,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,948評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蔗草,死亡現(xiàn)場(chǎng)離奇詭異咒彤,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)咒精,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,371評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門镶柱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人模叙,你說我怎么就攤上這事歇拆。” “怎么了范咨?”我有些...
    開封第一講書人閱讀 157,490評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵故觅,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我渠啊,道長(zhǎng)输吏,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,521評(píng)論 1 284
  • 正文 為了忘掉前任替蛉,我火速辦了婚禮评也,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘灭返。我一直安慰自己盗迟,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,627評(píng)論 6 386
  • 文/花漫 我一把揭開白布熙含。 她就那樣靜靜地躺著罚缕,像睡著了一般。 火紅的嫁衣襯著肌膚如雪怎静。 梳的紋絲不亂的頭發(fā)上邮弹,一...
    開封第一講書人閱讀 49,842評(píng)論 1 290
  • 那天黔衡,我揣著相機(jī)與錄音,去河邊找鬼腌乡。 笑死盟劫,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的与纽。 我是一名探鬼主播侣签,決...
    沈念sama閱讀 38,997評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼急迂!你這毒婦竟也來了影所?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,741評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤僚碎,失蹤者是張志新(化名)和其女友劉穎猴娩,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體勺阐,經(jīng)...
    沈念sama閱讀 44,203評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡卷中,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,534評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了渊抽。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蟆豫。...
    茶點(diǎn)故事閱讀 38,673評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖腰吟,靈堂內(nèi)的尸體忽然破棺而出无埃,到底是詐尸還是另有隱情徙瓶,我是刑警寧澤毛雇,帶...
    沈念sama閱讀 34,339評(píng)論 4 330
  • 正文 年R本政府宣布,位于F島的核電站侦镇,受9級(jí)特大地震影響灵疮,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜壳繁,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,955評(píng)論 3 313
  • 文/蒙蒙 一震捣、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧闹炉,春花似錦蒿赢、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,770評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至嗅钻,卻和暖如春皂冰,著一層夾襖步出監(jiān)牢的瞬間店展,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,000評(píng)論 1 266
  • 我被黑心中介騙來泰國(guó)打工秃流, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留赂蕴,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,394評(píng)論 2 360
  • 正文 我出身青樓舶胀,卻偏偏與公主長(zhǎng)得像概说,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子峻贮,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,562評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容