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