- WebGL 示例
- WebGL - 繪製點
- WebGL - 繪製三角形
- WebGL - 繪製模式
- WebGL - 繪製四邊形
- WebGL - 顏色
- WebGL - 平移
- WebGL - 縮放
- WebGL - 旋轉
- WebGL - 立方體旋轉
- WebGL - 互動式立方體
- WebGL 有用資源
- WebGL - 快速指南
- WebGL - 有用資源
- WebGL - 討論
WebGL - 幾何體
獲取 WebGL 上下文後,您必須定義基本圖形(您要繪製的物件)的幾何體並將其儲存。在 WebGL 中,我們使用 JavaScript 陣列定義幾何體的詳細資訊,例如頂點、索引、基本圖形的顏色。為了將這些詳細資訊傳遞給著色器程式,我們必須建立緩衝區物件並將包含資料的 JavaScript 陣列儲存(附加)到相應的緩衝區中。
注意:稍後,這些緩衝區物件將與著色器程式(頂點著色器)的屬性關聯。
定義所需的幾何體
使用頂點繪製的 2D 或 3D 模型稱為網格。網格中的每個面稱為多邊形,多邊形由 3 個或更多個頂點組成。
要在 WebGL 渲染上下文中繪製模型,您必須使用 JavaScript 陣列定義頂點和索引。例如,如果我們想要建立一個位於座標 {(5,5), (-5,5), (-5,-5)} 上的三角形,如所示,則可以為頂點建立一個數組,如下所示:
var vertices = [ 0.5,0.5, //Vertex 1 0.5,-0.5, //Vertex 2 -0.5,-0.5, //Vertex 3 ];
同樣,您可以為索引建立一個數組。上述三角形的索引將為 [0, 1, 2],可以定義為:
var indices = [ 0,1,2 ]
為了更好地理解索引,請考慮更復雜的模型,如正方形。我們可以將正方形表示為兩個三角形的集合。如果 (0,3,1) 和 (3,1,2) 是我們打算用來繪製正方形的兩個三角形,則索引將定義為:
var indices = [0,3,1,3,1,2];
注意:
為了繪製基本圖形,WebGL 提供了以下兩種方法:
drawArrays() - 使用此方法時,我們使用 JavaScript 陣列傳遞基本圖形的頂點。
drawElements() - 使用此方法時,我們使用 JavaScript 陣列傳遞基本圖形的頂點和索引。
緩衝區物件
緩衝區物件是 WebGL 提供的一種機制,它指示系統中分配的記憶體區域。在這些緩衝區物件中,您可以儲存要繪製的模型的資料,對應於頂點、索引、顏色等。
使用這些緩衝區物件,您可以透過其屬性變數之一將多個數據傳遞給著色器程式(頂點著色器)。由於這些緩衝區物件駐留在 GPU 記憶體中,因此可以對其進行直接渲染,從而提高效能。
為了處理幾何體,有兩種型別的緩衝區物件。它們是:
頂點緩衝區物件 (VBO) - 它儲存要渲染的圖形模型的每個頂點資料。我們在 WebGL 中使用頂點緩衝區物件來儲存和處理有關頂點的資料,例如頂點座標、法線、顏色和紋理座標。
索引緩衝區物件 (IBO) - 它儲存要渲染的圖形模型的索引(索引資料)。
定義所需的幾何體並將其儲存在 JavaScript 陣列中後,您需要將這些陣列傳遞給緩衝區物件,然後資料將傳遞給著色器程式。要將資料儲存在緩衝區中,需要遵循以下步驟。
建立一個空緩衝區。
將適當的陣列物件繫結到空緩衝區。
使用型別化陣列之一將資料(頂點/索引)傳遞給緩衝區。
取消繫結緩衝區(可選)。
建立緩衝區
要建立空緩衝區物件,WebGL 提供了一個名為createBuffer()的方法。如果建立成功,此方法將返回一個新建立的緩衝區物件;否則,如果失敗,則返回空值。
WebGL 作為狀態機執行。建立緩衝區後,任何後續緩衝區操作都將在當前緩衝區上執行,直到我們取消繫結它。使用以下程式碼建立緩衝區:
var vertex_buffer = gl.createBuffer();
注意 - gl 是當前 WebGL 上下文的引用變數。
繫結緩衝區
建立空緩衝區物件後,您需要將適當的陣列緩衝區(目標)繫結到它。WebGL 提供了一個名為bindBuffer()的方法來實現此目的。
語法
bindBuffer()方法的語法如下:
void bindBuffer (enum target, Object buffer)
此方法接受兩個引數,下面將對它們進行討論。
target - 第一個變數是列舉值,表示我們要繫結到空緩衝區的緩衝區型別。您有兩個預定義的列舉值可供此引數選擇。它們是:
ARRAY_BUFFER 表示頂點資料。
ELEMENT_ARRAY_BUFFER 表示索引資料。
Object buffer - 第二個是上一步中建立的緩衝區物件的引用變數。引用變數可以是頂點緩衝區物件或索引緩衝區物件的引用變數。
示例
以下程式碼片段顯示瞭如何使用 bindBuffer() 方法。
//vertex buffer var vertex_buffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer); //Index buffer var Index_Buffer = gl.createBuffer(); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, index_buffer);
將資料傳遞到緩衝區
下一步是將資料(頂點/索引)傳遞到緩衝區。到目前為止,資料採用陣列的形式,在將其傳遞到緩衝區之前,我們需要將其包裝在 WebGL 型別化陣列之一中。WebGL 提供了一個名為bufferData()的方法來實現此目的。
語法
bufferData() 方法的語法如下:
void bufferData (enum target, Object data, enum usage)
此方法接受三個引數,下面將對它們進行討論:
target - 第一個引數是列舉值,表示我們使用的陣列緩衝區型別。此引數的選項為:
ARRAY_BUFFER 表示頂點資料。
ELEMENT_ARRAY_BUFFER 表示索引資料。
Object data - 第二個引數是包含要寫入緩衝區物件的資料的物件值。這裡我們必須使用型別化陣列傳遞資料。
Usage - 此方法的第三個引數是一個列舉變數,指定如何使用緩衝區物件資料(儲存的資料)來繪製圖形。此引數有三個選項,如下所示。
gl.STATIC_DRAW - 資料將指定一次並使用多次。
gl.STREAM_DRAW - 資料將指定一次並使用幾次。
gl.DYNAMIC_DRAW - 資料將重複指定並使用多次。
示例
以下程式碼片段顯示瞭如何使用bufferData()方法。假設 vertices 和 indices 分別是儲存頂點和索引資料的陣列。
//vertex buffer gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW); //Index buffer gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
型別化陣列
WebGL 提供了一種稱為型別化陣列的特殊型別的陣列,用於傳輸索引頂點和紋理等資料元素。這些型別化陣列儲存大量資料並以本機二進位制格式處理它們,從而提高效能。WebGL 使用的型別化陣列有 Int8Array、Uint8Array、Int16Array、Uint16Array、Int32Array、UInt32Array、Float32Array 和 Float64Array。
注意
通常,為了儲存頂點資料,我們使用Float32Array;為了儲存索引資料,我們使用Uint16Array。
您可以像使用 JavaScript 陣列一樣使用new關鍵字建立型別化陣列。
取消繫結緩衝區
建議您在使用完緩衝區後取消繫結它們。這可以透過在緩衝區物件的位置傳遞空值來完成,如下所示。
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
WebGL 提供了以下方法來執行緩衝區操作:
| 序號 | 方法和描述 |
|---|---|
| 1 | void bindBuffer (enum target, Object buffer) target - ARRAY_BUFFER, ELEMENT_ARRAY_BUFFER |
| 2 | void bufferData(enum target, long size, enum usage) target - ARRAY_BUFFER, ELEMENT_ARRAY_BUFFER usage - STATIC_DRAW, STREAM_DRAW, DYNAMIC_DRAW |
| 3 | void bufferData (enum target, Object data, enum usage) target 和 usage - 與上面的bufferData相同 |
| 4 | void bufferSubData(enum target, long offset, Object data) target - ARRAY_BUFFER, ELEMENT_ARRAY_BUFFER |
| 5 | Object createBuffer() |
| 6 | void deleteBuffer(Object buffer) |
| 7 | any getBufferParameter(enum target, enum pname) target - ARRAY_BUFFER, ELEMENT_ ARRAY_BUFFER pname - BUFFER_SIZE, BUFFER_USAGE |
| 8 | bool isBuffer(Object buffer) |