摘要:我們的目標是將位置信心從程序中傳遞到頂點著色器,而變量就傳輸的是那些和頂點相關的數據。緩沖區對象是中的一塊存儲區域,其中保存了大量的頂點數據,可以一次性的向頂點著色器傳入多個頂點到變量。三角形一系列多帶帶的三角形。系列文章初探繪制三角形
該文章于一天前發表在 github,若有問題可提至 github。
在上一篇文章WebGL 初探中,我們熟悉了 WebGL 的簡單背景以及如何繪制一個簡單的點。但是只繪制點我們是無法進入三維世界的,本篇章將講解如何使用 WebGL 繪制三角形,因為很多 3D 圖形都是使用三角形為基礎進行渲染的,所以有些對 GPU 性能指標的評價就是渲染三角形的能力。
attribute 變量前一篇文章中,繪制一個點直接將一個硬編碼的矢量賦給了位置屬性。但是,顯然這樣寫是不夠靈活的。所以在這篇文章的前一部分會使用變量重些前一篇文章的例子。我們的目標是將位置信心從 JavaScript 程序中傳遞到頂點著色器,而 attribute 變量就傳輸的是那些和頂點相關的數據。下圖展示了如何使用 attribute 變量傳輸數據:
var VSHADER_SOURCE = "attribute vec4 a_Position; " + "void main() { " + " gl_Position = a_Position; " + " gl_PointSize = 10.0; " + "} ";
如上所示,前一篇文章中,直接將使用矢量進行賦值 gl_Position = vec4(0.0, 0.0, 0.0, 1.0)。而這里使用 attribute vec4 a_Position 聲明一個 attribute 變量。關鍵字 attribute 被稱為存儲限定符,表示聲明一個 attribute 變量,而且 attribute 變量必須聲明成全局變量,數據將從著色器外傳入。gl_Position = a_Position 將 attribute 變量 a_Position 賦值給 gl_Position。
// 獲得 attribute 變量 a_Position 的存儲位置 var a_Position = gl.getAttribLocation(gl.program, "a_Position"); if (a_Position < 0) { console.log("Failed to get the storage location of a_Position"); return; } // 將頂點位置傳遞給 attribute 變量 gl.vertexAttrib3f(a_Position, 0.0, 0.0, 0.0);
上面,我們使用 vertexAttrib3f(location, v0, v1, v2) 方法將數據 (v0, v1, v2) 傳遞給 location 參數指向的 attribute 變量。而這里的 location 是要修改的 attribute 變量的存儲位置。所以在這之前我們需要獲取 attribute 變量的存儲位置。這里,可以通過 getAttribLocation(program, name) 獲取 attribute 變量的存儲位置。進行完這些更改之后,運行會發現和上一篇文章相同的效果。
緩沖區對象到現在,我們一次只能繪制一個點,無法一次性繪制多個點,甚至是線和面。想要一次繪制多個點,我們需要借助一個叫做緩沖區對象的東西。緩沖區對象是 WebGL 中的一塊存儲區域,其中保存了大量的頂點數據,可以一次性的向頂點著色器傳入多個頂點到 attribute 變量。下圖展示了如何使用緩沖區對象:
var vertices = new Float32Array([ 0, 0.5, -0.5, -0.5, 0.5, -0.5 ]); // 創建緩沖區對象 var vertexBuffer = gl.createBuffer(); if (!vertexBuffer) { console.log("創建緩沖區對象失敗。"); return -1; } // 綁定緩沖區對象到目標 gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); // 將數據寫入緩沖區對象 gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW); var a_Position = gl.getAttribLocation(gl.program, "a_Position"); if (a_Position < 0) { console.log("獲得 attriute 變量 a_Position 失敗"); return -1; } // 將緩沖區對象賦值給 attriute 變量 a_Position gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0); // 開啟 attribute 變量 gl.enableVertexAttribArray(a_Position);
首先,是通過 createBuffer() 方法創建一個緩沖區對象,對應的方法還有 deleteBuffer() 用于刪除一個緩沖區對象。接著,使用 bindBuffer(target, buffer) 將緩沖區對象綁定到 WebGL 已經存在的目標上,以通知 WebGL 正確的處理其內容。緊接著,使用 bufferData(target, data, useage) 方法將數據寫入緩沖區,這里實際是將數據寫入到綁定的目標對象上,所以在第二步中進行了緩沖區對象的綁定。而第二個參數是一個定義好的類型化數組。這里的第三個參數,STATIC_DRAW 代表只會想緩沖區寫入一次,繪制多次,其它用法參數可查相關 API。然后,使用 vertexAttribPointer(location, size, type, normalized, stride, offset) 將緩沖區對象賦值給 attribute 變量。這里的第二個參數制定緩沖區對象的每個頂點的分量(1到4之間),如果 size 比 attribute 變量需要的分量小,則按照一定規則補全。第三個參數指定了數據格式。第四個參數表示是否將非浮點型數據歸一到 [0, 1] 或[-1,1] 之間。最后兩個參數一般默認為0,此處不做具體介紹。最后通過 enableVertexAttribArray(a_Position) 方法開啟緩沖區對象和 attribute 變量的連接。
繪制三角形最后,我么可通過 drawArrays(gl.TRIANGLES, 0, n) 繪制三角形。但是,前一篇文章中提到 drawArrays 函數功能非常強大?,F在,我們就看一下該函數有哪些強大的特性。該函數中第一個參數是指定繪制方式,第二個參數指定從哪個頂點開始繪制,第三個參數指定繪制需要多少個頂點。下表展示了第一個參數對應的繪制方式:
參數 | 基本圖形 | 呈現效果 |
---|---|---|
gl.POINTS | 點 | 一系列的點繪制在v0,v1,v2等處。 |
gl.LINES | 線段 | 一系列多帶帶線段。 |
gl.LINE_STRIP | 連線 | 一個相連的線段。 |
gl.LINE_LOOP | 回路 | 一個相連接的回路。 |
gl.TRIANGLES | 三角形 | 一系列多帶帶的三角形。 |
gl.TRIANGLE_STRIP | 三角帶 | 一個相鄰三角形組成的圖形。 |
下圖是 new Float32Array([0, 0.5, -0.5, -0.5, 0.0, 0.0, 0.5, -0.5]) 矢量的一個測試:
結語這篇文章主要講了如何利用緩沖區對象在空間中繪制點、線、面。下一篇文章將講解矩陣變換,有了這兩個知識的積累,理論上可以畫出我們想要的 3D 圖形。WebGL 的 API 看似復雜,但基本都很類似。當我們對這一套熟悉之后,我們會愈發輕車熟路。
系列文章WebGL 初探
繪制三角形
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/80679.html
摘要:那是因為,線條的光柵化過程和多邊形的光柵化過程并不是完全一致的。這將會導致一些本該被隱藏的線段,未被遮擋。原理我們知道,一般對象都是由三角形組成的。其中涉及到和的相關介紹,筆者將會在后續的文章中介紹。 如果要把一個對象的線框繪制出來,一般的方法是先繪制實體對象,然后通過gl.LINES的模式再繪制一遍模型,此時模型的線框就會被繪制出來。 gl.LINES的問題 此方法需要繪制兩遍對象...
摘要:在文末,我會附上一個可加載的模型方便學習中文藝術字渲染用原生可以很容易地繪制文字,但是原生提供的文字效果美化功能十分有限。 showImg(https://segmentfault.com/img/bVWYnb?w=900&h=385); WebGL 可以說是 HTML5 技術生態鏈中最為令人振奮的標準之一,它把 Web 帶入了 3D 的時代。 初識 WebGL 先通過幾個使用 Web...
閱讀 2665·2023-04-26 02:44
閱讀 8497·2021-11-22 14:44
閱讀 2123·2021-09-27 13:36
閱讀 2489·2021-09-08 10:43
閱讀 681·2019-08-30 15:56
閱讀 1396·2019-08-30 15:55
閱讀 2890·2019-08-28 18:12
閱讀 2832·2019-08-26 13:50