您的位置:首頁>正文

webgl自學筆記——幾何圖形

3D應用的基礎元素:

1、canvas, 它是渲染場景的預留位置。 標準html的canvas元素

2、Objects, 這裡指的是組成一個場景的所有3d實體。 這些實體都由三角形組成。 webgl中使用Buffer(vertex、index)來存儲管理這些3d實體資料。

3、Lights, 如果沒有光照3d場景將看不到任何東西。 webgl使用著色器來為場景中的光照建模。 我們將會看到3d實體如何根據物理規律來反射和吸收光照, 並討論不同的光照模型。

4、Camera, 攝像機作為3d世界的視口。 我們通過攝像機來開發和看到一個3d場景。 我們要理解如何根據不同的場景來使用不同的矩陣操作, 這些操作可以利用相機原理來建模。

webgl中的資料類型:

webgl對圖形有一種標準的處理方式, 與我們擁有的表面的複雜性和頂點個數無關。 只有兩種基礎的資料類型來表達3d物體的幾何形狀:vertices和indices(頂點和索引)。

Vertices:代表3d物體的拐點, 每一個頂點使用3個數字來表達想x,y,z;webgl中沒有提供api來將獨立的頂點傳遞到渲染管線中, 因此我們需要將所有的頂點放在一個JavaScript陣列中然後通過這個陣列來構造一個webgl頂點緩衝區(vertex buffer)。

Indices:索引是在一個給定3d場景的中的所有頂點的數位識別碼。 索引告訴webgl如何有序的來連結頂點來生成一個表面。 像頂點一樣, 索引也是存儲在JavaScript陣列中然後使用webgl索引緩衝區傳遞給webgl的渲染管線。

有兩種webgl 緩衝區來描述和處理幾何圖形:

包含頂點數據的緩衝區:Vertex Buffer Objects(VBO)

包含索引資料的緩衝區:Index Buffer Objects(IBO)

webgl的渲染管線:

Vertex Buffer Objects

VBO包含了webgl要求來描述將要渲染的幾何圖形的資料。 除了上面提到的頂點座標外, 還有vertex normal(頂點法線), 顏色、紋理座標等都可以用vbo來建模。

Vertex shader

頂點著色器將會來每個頂點上被調用, 頂點著色器將用來操作之前的頂點資料, 如頂點座標、法線、顏色、文理座標。 這些資料將被頂點著色器內置的attributes變數來引用, 每一個attribute指向一個他讀取頂點資料的VBO。

Fragment shader

每三個頂點定義了一個三角形在三角形表面的每一個元素都需要被分配一個顏色, 否則我們的表面將是透明的。

三角形表面的每一個元素成為一個片元(fragment)。 因為我們處理的表面將被呈現在我們螢幕上, 所以片元通常被理解為圖元。

片元著色器的主要目的是為表面的每個獨立圖元來計算顏色。

Framebuffer

它是包含一個之前被片元著色器處理的片元二維的緩衝區。 一旦所有的片元都被處理過後, 一張二維圖片將被構造並顯示在螢幕上。 framebuffer是渲染管道的最終點。

Attributes, uniforms, varyings是著色器程式設計中經常用到的三種類型的變數。

Attributes是頂點著色器中的輸入變數, 如頂點座標、頂點顏色等。 由於頂點著色器將會在每個頂點上都被調用, 所以每次頂點著色器被調用時的輸入變數attributes都是不同的。

Uniforms 是在頂點著色器和片元著色器中都能被使用的輸入變數。 在一個渲染迴圈中unifroms通常是不變的常量。 如燈源位置。

Varyings用來由頂點著色器向片元著色器傳遞資料。

1、webgl緩衝區資料處理流程:

ver vertices = ;

var myBuffer = gl.createBuffer; // 創建緩衝區

// 綁定緩衝區; 由於webgl是一個狀態機, 一旦綁定buffer,

之後所有的緩衝操作都將在綁定的buffer上執行, 直到解綁這個buffer或者綁定到另一個buffer上。

gl.bindBuffer(gl.ARRAY_BUFFER, myBuffer);

// 綁定緩衝區後我們需要為他分配內容, webgl不能直接使用JavaScript陣列, 而是使用類型陣列, 以便緩衝區物件能夠使用原生二進位資料來加快圖形處理速度。

gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);

gl.bindBuffer(gl.ARRAY_BUFFER, null);// 清空緩存

2、將attributes連接到VBOs

VBO創建後, 我們需要將這些緩衝區連結到頂點著色器的屬性中。 每一個頂點著色器的attribute將且僅將指向一個緩衝區物件。

通常來講我們有以下對應關係。

緩衝區資料進入頂點著色器分為三步:

1)綁定一個緩衝區:gl.bindBuffer(gl.ARRAY_BUFFER, myBuffer)

2 ) 將一個attribute指向剛剛綁定的VBO:gl.vertexAttribPointer(Index, Size, Type, Norm, Stride, Offset);(該函式定義了一個從當前綁定緩衝區讀取資訊的指標;參數Index指的是將被匹配緩衝區的attribute的索引)

3)啟動attribute:gl.enableVertexAttribArray(aVertexPosition)

下面的圖表記錄了匹配過程

3、渲染

定義完VBO物件並綁定到頂點著色器屬性後,

就可以準備渲染了。 完成渲染過程我們可以使用兩個API函數:drawArrays、drawElements

這兩個方法都是用來像框架緩衝區中寫入資料;drawArrays按照在緩衝區中的頂點資料的順序來創建圖形, 相反drawElements使用索引來訪問頂點緩衝區中的資料來創建圖形。

drawArrays和drawElements僅接受 enabled arrays, 他們是被匹配到啟動的頂點著色器attribute的vbo物件。

當索引資訊無法獲得時, 我們使用drawArrays方法。 在大多數情況下當幾何圖形很簡單以至於定義索引是浪費資源時我們使用drawArrays方法, 比如三角形、矩形。

使用drawArrays只適合非常簡單的圖形, 如果是連續三角形, 那麼vbo中需要重複定義每個頂點, 並且這些點都會在頂點著色器中被處理, 浪費空間和性能。

gl.drawArrays(Mode, First, Count)

drawElements允許使用IBO來告訴流覽器如何去渲染圖形。 因為有了索引VBO中的資料不用像之前一樣被重複定義,只需要定義一次,但可以通過索引來多次使用。這種方式減少記憶體和GPU的性能損耗。

使用drawElements至少需要兩個Buffer:VBO和IBO;頂點著色器將在每一個VBO的頂點上執行,然後渲染管線使用IBO將幾何圖形聚集成三角形。(確保VBO、IBO都被綁定過)

gl.drawElements(Mode, Count, Type, Offset)

webgl作為一個狀態機的buffer控制

我們可以拿到一些關於渲染管線狀態的資訊,比如:

getParameter(type)

ARRAY_BUFFER_BINDING取得一份關於最近綁定的VBO的引用

ELEMENT_ARRAY_BUFFER取得一份關於最近綁定的IBO的引用

getBufferParameter(type, parameter)

type: ARRAY_BUFFER, ELEMENT_ARRAY_BUFFER

parameter: BUFFER_SIZE, BUFFER_USAGE

isBuffer(object)

基本步驟:

initProgram

initBuffers

drawSence

創建著色器三步驟:

var shader = gl.createShader; gl.shaderSource(shader, source); gl.compileShader(shader); gl.getShaderParameter(shader, gl.COMPILE\_STATUS);

initProgram步驟:

prg = gl.createProgram; gl.attachShader(prg, shader); // vs fs gl.linkProgram(prg); gl.getProgramParameter(prg, gl.LINK\_STATUS) gl.useProgram(prg);

prg.aVertexPosition = gl.getAttribLocation(prg, 'aVertexPosition');

因為有了索引VBO中的資料不用像之前一樣被重複定義,只需要定義一次,但可以通過索引來多次使用。這種方式減少記憶體和GPU的性能損耗。

使用drawElements至少需要兩個Buffer:VBO和IBO;頂點著色器將在每一個VBO的頂點上執行,然後渲染管線使用IBO將幾何圖形聚集成三角形。(確保VBO、IBO都被綁定過)

gl.drawElements(Mode, Count, Type, Offset)

webgl作為一個狀態機的buffer控制

我們可以拿到一些關於渲染管線狀態的資訊,比如:

getParameter(type)

ARRAY_BUFFER_BINDING取得一份關於最近綁定的VBO的引用

ELEMENT_ARRAY_BUFFER取得一份關於最近綁定的IBO的引用

getBufferParameter(type, parameter)

type: ARRAY_BUFFER, ELEMENT_ARRAY_BUFFER

parameter: BUFFER_SIZE, BUFFER_USAGE

isBuffer(object)

基本步驟:

initProgram

initBuffers

drawSence

創建著色器三步驟:

var shader = gl.createShader; gl.shaderSource(shader, source); gl.compileShader(shader); gl.getShaderParameter(shader, gl.COMPILE\_STATUS);

initProgram步驟:

prg = gl.createProgram; gl.attachShader(prg, shader); // vs fs gl.linkProgram(prg); gl.getProgramParameter(prg, gl.LINK\_STATUS) gl.useProgram(prg);

prg.aVertexPosition = gl.getAttribLocation(prg, 'aVertexPosition');

同類文章
Next Article
喜欢就按个赞吧!!!
点击关闭提示