豆皮粉兒,又見面啦!今天由字節跳動的"yancy"童鞋給你們重磅推出一篇WebGL
的乾貨"WebGL基礎:着色器基礎"!準備好了嗎?接下來讓咱們開啓奇幻旅程,進入 3D
的世界。javascript
本文做者:yancyjava
3D
首先咱們要介紹的是幾個概念,這是咱們要進入到 3D
不可或缺的內容。認識一下它們吧。編程
這幾個概念在WebGL
中屬於最多見的內容。緩存
實際生活中,咱們的目光老是以咱們的眼睛爲起始點,到達咱們想要看到的物體,同時,隨着咱們觀察的角度不一樣,物體也會呈現不同的形態。以一張圖說明吧。markdown
如此幾個內容,建立出了3D
世界的基本顯示模型,因而可知其重要程度。後面咱們也會說到如何在 WebGL
中設定這幾個內容。也會有的小夥伴把視點稱爲相機,目標點稱爲畫布。實際上是同樣的道理。按照本身的理解記憶就好。函數
可視範圍指的是咱們所能看到的最大範圍。如:通常狀況下咱們看不到本身身後的事物。性能
衆所周知,三維物體具備深度的概念。在咱們的理解中,深度就是 z
軸。測試
雖然咱們能夠將物體放置在三維空間中的任何位置,可是在WebGL
中,可視範圍以外的物體是不被繪製的,這也是爲了節省開銷。spa
水平視角、垂直視角、可視深度
定義了可視空間的概念。設計
可視空間分爲兩種。
若是想渲染 3D
圖形,就須要通過一系列的步驟,這些步驟稱爲渲染管線。在開發 WebGL
程序時,咱們就須要經過着色器語言跟GPU進行溝通,用來設定咱們須要渲染和顯示的圖形。
因而可知:着色器是編寫WebGL
時最重要的一點(沒有之一)。咱們之因此能生成並操做3D
圖像,都是由於着色器在起做用。WebGL
中着色器分爲兩種。頂點着色器和片元着色器。
這裏的頂點表明的是組成物體的每個點。
頂點着色器的功能主要是將位置數據通過矩陣變換、計算光照以後生成頂點顏色、變換紋理座標。並將生成的數據輸出到片元着色器。
片元着色器的做用是將光柵化階段生成的每一個片元,計算出每一個片元的最終元素。
注:
因爲着色器內容比較重要,這裏咱們先引入這兩個概念,先簡單理解就能夠,後面專門對着色器進行分享。
瞭解了第一小節的內容以後,咱們開始進入到WebGL
開發實戰中。
還記得Canvas
中第一步須要幹什麼嗎?
沒錯,須要獲取 Canvas
元素和繪圖上下文。WebGL
開發也不例外,也須要首先獲取元素和繪圖上下文。形以下方代碼所示:
獲取到繪圖上下文以後,咱們須要初始化WebGL
的着色器了,着色器代碼是以字符串的形式嵌入到渲染程序中,因此咱們須要編寫兩個着色器的字符串。
兩個着色器代碼都是以字符串的形式存在,並在執行渲染時嵌入到渲染流程內。
說明:
void main() {}
: 建立一個主函數。gl_Position
: 指定繪製的座標,接收一個擁有4個浮點份量的vec4
數據。分別表明 x,y,z,w
數據gl_PointSize
: 表示要繪製圖形的尺寸大小。gl_FragColor
: 定義圖形顏色,1.0 0.0 0.0 1.0
分別表明r g b a
固然,只是編寫完着色器代碼依然不能完成渲染工做,接下來咱們就須要將着色器添加到渲染流程內
完成上述兩步以後,咱們就須要將着色器代碼添加到着色器中。看下例子。
完成編譯以後,咱們須要將着色器添加到渲染程序中。
完成上述步驟以後,就能夠繪製咱們的圖形了。這裏咱們以一個點爲例。在畫布上繪製一個點出來。
gl.drawArrays(gl.POINTS, 0, 1);
複製代碼
此時就能夠打開頁面,看到咱們繪製的這個點了。
總結代碼:
WebGL
的渲染依賴底層 GPU
的渲染能力。因此 WebGL
渲染流程和 GPU
內部的渲染管線是相符的。
渲染管線的做用是將3D模型轉換爲2維圖像。
在早期,渲染管線是不可編程的,叫作固定渲染管線,工做的細節流程已經固定,修改的話須要調整一些參數。
現代的 GPU
所包含的渲染管線爲可編程渲染管線,能夠經過編程 GLSL,着色器語言
來控制一些渲染階段的細節。
(心理承受弱的同窗可跳過此小節)
WebGL
的渲染過程分爲如下幾項:
這裏一系列的名詞可能會嚇到不少同窗,千萬別被名詞嚇到喲,接下來的過程當中會詳細說明。也但願經過本文可讓你們理解基本的渲染流程。附圖解一張,助你們理解。
頂點着色器的做用是經過計算得到最終的頂點座標, 如:
A --> () => {…………} ==> A1
:座標 A
通過一系列的計算,最終獲取座標 A1
B --> () => {…………} ==> B1
:座標 B
通過一系列的計算,最終獲取座標 B1
頂點着色器計算出來的座標將會渲染到最終的顯示畫布上。
此外,頂點着色器還會計算以下內容:顏色、紋理座標、頂點尺寸……
在頂點着色器階段一般會涉及到三個類型的變量。
像 attribute
這個變量以前咱們就用到過,用來設置了頂點的位置和大小。 回顧一下
其餘的兩個變量暫時沒有用到,接下來的內容裏會用到這兩種類型的變量。敬請期待😁
什麼是圖元?
描述各類圖形元素的函數叫作圖元,描述幾何元素的稱爲幾何圖元(點,線段或多邊形)。點和線是最簡單的幾何圖元
通過頂點着色器計算以後的座標會被組裝成組合圖元。
接下來經過一組圖解來看看渲染器如何進行圖元裝配和光柵化
圖元就是一個點、一條線段、或者是一個多邊形。
什麼是圖元裝配呢? 簡單理解就是說將咱們設置的頂點、顏色、紋理等內容組裝稱爲一個可渲染的多邊形的過程。
注意:
如何組裝取決於 gl.drawArrays(type, count)
中的 type
類型,本文最後有詳細的內容。
在以前的文章裏,咱們就使用 gl.POINTS
來繪製了一個點。
片元:二維圖象上每一個點都包含了顏色、深度和紋理數據。這樣一個點稱爲片元
光柵化能夠簡單理解爲如下內容:
經過圖元裝配生成的多邊形,計算像素並填充,剔除不可見的部分,剪裁掉不在可視範圍內的部分。最終生成可見的帶有顏色數據的圖形並繪製。
光柵化流程圖解:
WebGL
中,咱們也能夠設定物體的背面不可見,那麼在渲染過程當中,就會將不可見的部分剔除,不參與繪製。節省渲染開銷。接收光柵化階段生成的片元,在光柵化階段中,已經計算出每一個片元的顏色信息,這一階段會將片元作逐片元挑選的操做,處理過的片元會繼續向後面的階段傳遞。
經過模板測試和深度測試來肯定片元是否要顯示,測試過程當中會丟棄掉部分無用的片元內容,而後生成可繪製的二維圖像繪製並顯示。
z
軸的值作測試,值比較小的片元內容會覆蓋值比較大的。(相似於近處的物體會遮擋遠處物體)。下面結合2.2.5的代碼,咱們進行流程分析,加深理解。
分析:
首先建立了兩個變量 VERTEX_SHADER 頂點着色器
和 FRAGMENT_SHADER 片元着色器
。這兩個內容會經過下面的代碼添加到頂點着色器和片元着色器中。
以後經過 gl.createShader()
建立了兩個着色器。傳入不一樣的參數便可建立不一樣的着色器。建立並關聯着色器的步驟比較複雜。當你熟悉這個過程以後,能夠將這個過程的代碼封裝起來做爲備用。
接下來,經過 將着色器代碼添加到着色器中、編輯着色器、建立程序對象、將着色器添加到程序對象中、關聯程序對象、使用程序對象
這一系列的步驟初始化着色器和程序對象。
當全部的前置工做準備就緒以後,就能夠調用 gl.drawArrays()
方法來繪製想要的圖形。
type
表明要繪製的圖形形狀,值有如下幾種:gl.POINTS: 要繪製一系列的點
gl.LINES: 要繪製了一系列未鏈接直線段(單獨行) gl.LINE_STRIP: 要繪製一系列鏈接的線段
**gl.LINE_LOOP **: 要繪製一系列鏈接的線段。它還鏈接第一個和最後一個頂點,以造成一個環
gl.TRIANGLES: 一系列單獨的三角形
gl.TRIANGLE_STRIP: 繪製一個三角帶
gl.TRIANGLE_FAN: 繪製一個扇形(三角扇)
first
表明從哪一個點開始count
表明須要使用幾個點其餘的形狀能夠本身嘗試…………會有意想不到的效果。