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
]; 

Geometry

同樣,您可以為索引建立一個數組。上述三角形的索引將為 [0, 1, 2],可以定義為:

var indices = [ 0,1,2 ]

為了更好地理解索引,請考慮更復雜的模型,如正方形。我們可以將正方形表示為兩個三角形的集合。如果 (0,3,1) 和 (3,1,2) 是我們打算用來繪製正方形的兩個三角形,則索引將定義為:

var indices = [0,3,1,3,1,2];

Geometry Example

注意

為了繪製基本圖形,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)

targetusage - 與上面的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)
廣告

© . All rights reserved.