WebGL基礎:著色器基礎知識

今天由位元組跳動的“yancy”童鞋給大家重磅推出一篇

WebGL

的乾貨接下來讓我們開啟奇幻旅程,進入

3D

的世界。

本文作者:yancy

1. 認識3D

首先我們要介紹的是幾個概念,這是我們要進入到

3D

不可或缺的內容。認識一下它們吧。

1.1 視點,視線,目標點,上方向

這幾個概念在

WebGL

中屬於最常見的內容。

視點:可以簡易的理解為眼睛,也叫觀察點

目標點:可以理解為我們要看的物體(任何物體)

上方向:頭頂的方向。

實際生活中,我們的目光總是以我們的眼睛為起始點,到達我們想要看到的物體,同時,隨著我們觀察的角度不同,物體也會呈現不一樣的形態。以一張圖說明吧。

WebGL基礎:著色器基礎知識

如此幾個內容,創建出了

3D

世界的基本顯示模型,由此可見其重要程度。後面我們也會說到如何在

WebGL

中設定這幾個內容。也會有的小夥伴把

視點稱為相機

目標點稱為畫布

。其實是一樣的道理。按照自己的理解記憶就好。

1.2 可視範圍

可視範圍指的是我們所能看到的最大範圍。如:一般情況下我們看不到自己身後的事物。眾所周知,三維物體具有深度的概念。在我們的理解中,深度就是

z

軸。雖然我們可以將物體放置在三維空間中的任何位置,但是在

WebGL

中,可視範圍之外的物體是不被繪製的,這也是為了節省開銷。

1.3 可視空間

水平視角、垂直視角、可視深度

定義了可視空間的概念。可視空間分為兩種。

正射投影:與物體的遠近無關,通常用在建築設計和建模上。

WebGL基礎:著色器基礎知識

透視投影:我們平時觀察的真實世界都是透視投影。更有深度的感覺。

WebGL基礎:著色器基礎知識

1.3 著色器

如果想渲染

3D

圖形,就需要經過一系列的步驟,這些步驟稱為渲染管線。在開發

WebGL

程式時,我們就需要透過著色器語言跟GPU進行溝通,用來設定我們需要渲染和顯示的圖形。由此可見:著色器是編寫

WebGL

時最重要的一點(沒有之一)。我們之所以能生成並操作

3D

影象,都是因為著色器在起作用。

WebGL

中著色器分為兩種。

頂點著色器和片元著色器

1。3。1 頂點著色器

這裡的頂點代表的是組成物體的每一個點。*

頂點著色器的功能主要是將位置資料經過矩陣變換、計算光照之後生成頂點顏色、變換紋理座標。並將生成的資料輸出到片元著色器。

1。3。2 片元著色器

片元著色器的作用是將

光柵化階段

生成的每個片元,計算出每個片元的最終元素。

注:*

由於著色器內容比較重要,這裡我們先引入這兩個概念,先簡單理解就可以,後面專門對著色器進行分享。

2. 繪製圖形

2.1 獲取繪圖上下文

瞭解了第一小節的內容之後,我們開始進入到

WebGL

開發實戰中。還記得

Canvas

中第一步需要幹什麼嗎?沒錯,需要獲取

Canvas

元素和繪圖上下文。

WebGL

開發也不例外,也需要首先獲取元素和繪圖上下文。形如下方程式碼所示:

WebGL基礎:著色器基礎知識

2.2 初始化著色器

2。2。1。 編寫著色器程式碼

獲取到繪圖上下文之後,我們需要初始化

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

2。2。2。 建立著色器

當然,只是編寫完著色器程式碼依然不能完成渲染工作,接下來我們就需要將著色器新增到渲染流程內

WebGL基礎:著色器基礎知識

2。2。3。 著色器編譯

完成上述兩步之後,我們就需要將著色器程式碼新增到著色器中。看下例子。

WebGL基礎:著色器基礎知識

2。2。4。 建立 program

完成編譯之後,我們需要將著色器新增到渲染程式中。

WebGL基礎:著色器基礎知識

2。2。5。 繪製圖形

完成上述步驟之後,就可以繪製我們的圖形了。這裡我們以一個點為例。在畫布上繪製一個點出來。

gl。drawArrays(gl。POINTS, 0, 1);

此時就可以開啟頁面,看到我們繪製的這個點了。總結程式碼:

WebGL基礎:著色器基礎知識

3. 渲染管線

3.1 基礎內容介紹

WebGL

的渲染依賴底層

GPU

的渲染能力。所以

WebGL

渲染流程和

GPU

內部的渲染管線是相符的。

渲染管線的作用是將3D模型轉換為2維影象。*

在早期,渲染管線是不可程式設計的,叫做

固定渲染管線

,工作的細節流程已經固定,修改的話需要調整一些引數。現代的

GPU

所包含的渲染管線為

可程式設計渲染管線

,可以透過程式設計

GLSL,著色器語言

來控制一些渲染階段的細節。

3.2 渲染過程

(心理承受弱的同學可跳過此小節)*

WebGL

的渲染過程分為以下幾項:

頂點著色器

圖片裝配

光柵化

片元著色器

逐片段操作(本文不會分享此內容)

裁剪測試

多重取樣操作

背面剔除

模板測試

深度測試

融合

快取

這裡一系列的名詞可能會嚇到很多同學,千萬別被名詞嚇到喲,接下來的過程中會詳細說明。也希望透過本文可以讓大家理解基本的渲染流程。附圖解一張,助大家理解。

WebGL基礎:著色器基礎知識

4. 頂點著色器

頂點著色器的作用是透過計算獲得最終的頂點座標*

, 如:

A ——> () => {…………} ==> A1

:座標

A

經過一系列的計算,最終獲取座標

A1

B ——> () => {…………} ==> B1

:座標

B

經過一系列的計算,最終獲取座標

B1

…………頂點著色器計算出來的座標將會渲染到最終的顯示畫布上。此外,頂點著色器還會計算如下內容:

顏色、紋理座標、頂點尺寸……

在頂點著色器階段通常會涉及到三個型別的變數。

attribute

:針對單一頂點生效。

通常用於:頂點位置、頂點大小等內容

uniform

:影響所有頂點

通常用於:旋轉、平移、縮放等位置變換、顏色處理等內容。

varying

:可透過頂點著色器傳入到片元著色器。像

attribute

這個變數之前我們就用到過,用來設定了頂點的位置和大小。 回顧一下

WebGL基礎:著色器基礎知識

其他的兩個變數暫時沒有用到,接下來的內容裡會用到這兩種型別的變數。敬請期待

5. 圖元裝配和光柵化

什麼是圖元?*

官方解釋:

描述各種圖形元素的函式叫做圖元,描述幾何元素的稱為幾何圖元(點,線段或多邊形)。點和線是最簡單的幾何圖元

經過頂點著色器計算之後的座標會被組裝成

組合圖元

接下來透過一組圖解來看看渲染器如何進行圖元裝配和光柵化

通俗解釋

圖元就是一個點、一條線段、或者是一個多邊形。*

5.1 圖元裝配

什麼是圖元裝配呢?簡單理解就是說將我們設定的頂點、顏色、紋理等內容組裝稱為一個可渲染的多邊形的過程。

注意:*

如何組裝取決於

gl。drawArrays(type, count)

中的

type

型別,本文最後有詳細的內容。在之前的文章裡,我們就使用

gl。POINTS

來繪製了一個點。

5.2 光柵化

片元:二維圖象上每個點都包含了顏色、深度和紋理資料。這樣一個點稱為片元*

光柵化可以簡單理解為以下內容:透過圖元裝配生成的多邊形,計算畫素並填充,

剔除

不可見的部分,

剪裁

掉不在可視範圍內的部分。最終生成可見的帶有顏色資料的圖形並繪製。光柵化流程圖解:

WebGL基礎:著色器基礎知識

剔除和剪裁

剔除

:舉一個日常生活中的栗子來說明吧。

在日常生活中,對於不透明物體,背面對於觀察者來說是不可見的。同樣,在

WebGL

中,我們也可以設定物體的背面不可見,那麼在渲染過程中,就會將不可見的部分剔除,不參與繪製。節省渲染開銷。

剪裁

:同樣舉例子來說明

日常生活中不論是在看電視還是觀察物體,都會有一個可視範圍,在可視範圍之外的事物我們是看不到的。類似的,圖形生成後,有的部分可能位於可視範圍之外,這一部分會被剪裁掉,不參與繪製。以此來提高效能。

6. 片元著色器

接收光柵化階段生成的片元,在光柵化階段中,已經計算出每個片元的顏色資訊,這一階段會將片元做逐片元挑選的操作,處理過的片元會繼續向後面的階段傳遞。

逐片元挑選

透過模板測試和深度測試來確定片元是否要顯示,測試過程中會丟棄掉部分無用的片元內容,然後生成可繪製的二維影象繪製並顯示。

深度測試:

就是對

z

軸的值做測試,值比較小的片元內容會覆蓋值比較大的。(類似於近處的物體會遮擋遠處物體)。

模板測試:

模擬觀察者的觀察行為,可以接為映象觀察。標記所有映象中出現的片元,最後只繪製有標記的內容。

7. 例項分析

下面結合2。2。5的程式碼,我們進行流程分析,加深理解。

分析:*

首先建立了兩個變數

VERTEX_SHADER 頂點著色器

FRAGMENT_SHADER 片元著色器

。這兩個內容會透過下面的程式碼新增到頂點著色器和片元著色器中。

之後透過

gl。createShader()

建立了兩個著色器。傳入不同的引數即可建立不同的著色器。建立並關聯著色器的步驟比較複雜。當你熟悉這個過程之後,可以將這個過程的程式碼封裝起來作為備用。

接下來,透過

將著色器程式碼新增到著色器中、編輯著色器、建立程式物件、將著色器新增到程式物件中、關聯程式物件、使用程式物件

這一系列的步驟初始化著色器和程式物件。

當所有的前置工作準備就緒之後,就可以呼叫

gl。drawArrays()

方法來繪製想要的圖形。

7.1 gl.drawArrays(type, first, count)

1。

type

代表要繪製的圖形形狀,值有以下幾種:

gl.POINTS

: 要繪製一系列的點

gl.LINES

: 要繪製了一系列未連線直線段(單獨行)

gl.LINE_STRIP

: 要繪製一系列連線的線段

*

gl。LINE_LOOP *

: 要繪製一系列連線的線段。它還連線第一個和最後一個頂點,以形成一個環

gl.TRIANGLES

: 一系列單獨的三角形

gl.TRIANGLE_STRIP

: 繪製一個三角帶

gl.TRIANGLE_FAN

: 繪製一個扇形(三角扇)

2。

first

代表從哪個點開始

3。

count

代表需要使用幾個點

栗子:

WebGL基礎:著色器基礎知識

其他的形狀可以自己嘗試…………會有意想不到的效果。

文章為原創文章,若有侵權請聯絡;

頂部