webgl基礎:着色器基礎

豆皮粉兒,又見面啦!今天由字節跳動的"yancy"童鞋給你們重磅推出一篇WebGL的乾貨"WebGL基礎:着色器基礎"!準備好了嗎?接下來讓咱們開啓奇幻旅程,進入 3D 的世界。javascript

本文做者:yancyjava

1. 認識3D

首先咱們要介紹的是幾個概念,這是咱們要進入到 3D 不可或缺的內容。認識一下它們吧。編程

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

這幾個概念在WebGL中屬於最多見的內容。緩存

  • 視點:能夠簡易的理解爲眼睛,也叫觀察點
  • 目標點:能夠理解爲咱們要看的物體(任何物體)
  • 上方向:頭頂的方向。

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

如此幾個內容,建立出了3D世界的基本顯示模型,因而可知其重要程度。後面咱們也會說到如何在 WebGL 中設定這幾個內容。也會有的小夥伴把視點稱爲相機目標點稱爲畫布。實際上是同樣的道理。按照本身的理解記憶就好。函數

1.2 可視範圍

可視範圍指的是咱們所能看到的最大範圍。如:通常狀況下咱們看不到本身身後的事物。性能

衆所周知,三維物體具備深度的概念。在咱們的理解中,深度就是 z 軸。測試

雖然咱們能夠將物體放置在三維空間中的任何位置,可是在WebGL中,可視範圍以外的物體是不被繪製的,這也是爲了節省開銷。spa

1.3 可視空間

水平視角、垂直視角、可視深度 定義了可視空間的概念。設計

可視空間分爲兩種。

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

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

1.3 着色器

若是想渲染 3D 圖形,就須要通過一系列的步驟,這些步驟稱爲渲染管線。在開發 WebGL 程序時,咱們就須要經過着色器語言跟GPU進行溝通,用來設定咱們須要渲染和顯示的圖形。

因而可知:着色器是編寫WebGL時最重要的一點(沒有之一)。咱們之因此能生成並操做3D圖像,都是由於着色器在起做用。WebGL中着色器分爲兩種。頂點着色器和片元着色器

1.3.1 頂點着色器

這裏的頂點表明的是組成物體的每個點。

頂點着色器的功能主要是將位置數據通過矩陣變換、計算光照以後生成頂點顏色、變換紋理座標。並將生成的數據輸出到片元着色器。

1.3.2 片元着色器

片元着色器的做用是將光柵化階段生成的每一個片元,計算出每一個片元的最終元素。

注:

因爲着色器內容比較重要,這裏咱們先引入這兩個概念,先簡單理解就能夠,後面專門對着色器進行分享。

2. 繪製圖形

2.1 獲取繪圖上下文

瞭解了第一小節的內容以後,咱們開始進入到WebGL開發實戰中。

還記得Canvas中第一步須要幹什麼嗎?

沒錯,須要獲取 Canvas 元素和繪圖上下文。WebGL 開發也不例外,也須要首先獲取元素和繪圖上下文。形以下方代碼所示:

2.2 初始化着色器

2.2.1. 編寫着色器代碼

獲取到繪圖上下文以後,咱們須要初始化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. 建立着色器

固然,只是編寫完着色器代碼依然不能完成渲染工做,接下來咱們就須要將着色器添加到渲染流程內

2.2.3. 着色器編譯

完成上述兩步以後,咱們就須要將着色器代碼添加到着色器中。看下例子。

2.2.4. 建立 program

完成編譯以後,咱們須要將着色器添加到渲染程序中。

2.2.5. 繪製圖形

完成上述步驟以後,就能夠繪製咱們的圖形了。這裏咱們以一個點爲例。在畫布上繪製一個點出來。

gl.drawArrays(gl.POINTS, 0, 1);
複製代碼

此時就能夠打開頁面,看到咱們繪製的這個點了。

總結代碼:

3. 渲染管線

3.1 基礎內容介紹

WebGL 的渲染依賴底層 GPU 的渲染能力。因此 WebGL 渲染流程和 GPU 內部的渲染管線是相符的。

渲染管線的做用是將3D模型轉換爲2維圖像。

在早期,渲染管線是不可編程的,叫作固定渲染管線,工做的細節流程已經固定,修改的話須要調整一些參數。

現代的 GPU 所包含的渲染管線爲可編程渲染管線,能夠經過編程 GLSL,着色器語言 來控制一些渲染階段的細節。

3.2 渲染過程

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

WebGL 的渲染過程分爲如下幾項:

  • 頂點着色器
  • 圖片裝配
  • 光柵化
  • 片元着色器
  • 逐片斷操做(本文不會分享此內容)
    • 裁剪測試
    • 多重採樣操做
    • 背面剔除
    • 模板測試
    • 深度測試
    • 融合
    • 緩存

這裏一系列的名詞可能會嚇到不少同窗,千萬別被名詞嚇到喲,接下來的過程當中會詳細說明。也但願經過本文可讓你們理解基本的渲染流程。附圖解一張,助你們理解。

4. 頂點着色器

頂點着色器的做用是經過計算得到最終的頂點座標, 如:

  • A --> () => {…………} ==> A1:座標 A 通過一系列的計算,最終獲取座標 A1
  • B --> () => {…………} ==> B1:座標 B 通過一系列的計算,最終獲取座標 B1
  • …………

頂點着色器計算出來的座標將會渲染到最終的顯示畫布上。

此外,頂點着色器還會計算以下內容:顏色、紋理座標、頂點尺寸……

在頂點着色器階段一般會涉及到三個類型的變量。

  • attribute:針對單一頂點生效。
    • 一般用於:頂點位置、頂點大小等內容
  • uniform:影響全部頂點
    • 一般用於:旋轉、平移、縮放等位置變換、顏色處理等內容。
  • varying:可經過頂點着色器傳入到片元着色器。

attribute 這個變量以前咱們就用到過,用來設置了頂點的位置和大小。 回顧一下

其餘的兩個變量暫時沒有用到,接下來的內容裏會用到這兩種類型的變量。敬請期待😁

5. 圖元裝配和光柵化

什麼是圖元?

官方解釋:

描述各類圖形元素的函數叫作圖元,描述幾何元素的稱爲幾何圖元(點,線段或多邊形)。點和線是最簡單的幾何圖元

通過頂點着色器計算以後的座標會被組裝成組合圖元

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

通俗解釋

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

5.1 圖元裝配

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

注意:

如何組裝取決於 gl.drawArrays(type, count) 中的 type 類型,本文最後有詳細的內容。

在以前的文章裏,咱們就使用 gl.POINTS 來繪製了一個點。

5.2 光柵化

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

光柵化能夠簡單理解爲如下內容:

經過圖元裝配生成的多邊形,計算像素並填充,剔除不可見的部分,剪裁掉不在可視範圍內的部分。最終生成可見的帶有顏色數據的圖形並繪製。

光柵化流程圖解:

剔除和剪裁
  • 剔除:舉一個平常生活中的栗子來講明吧。
    • 在平常生活中,對於不透明物體,背面對於觀察者來講是不可見的。一樣,在 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 表明須要使用幾個點
栗子:

其餘的形狀能夠本身嘗試…………會有意想不到的效果。

相關文章
相關標籤/搜索