自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

圖解WebGL&Three.js工作原理

開發(fā) 前端
我們講兩個東西:WebGL背后的工作原理是什么?以Three.js為例,講述框架在背后扮演什么樣的角色?

[[214750]]

“哥,你又來啦?”

“是啊,我隨便逛逛。”

“別介啊……給我20分鐘,成不?”

“5分鐘吧,我很忙的。”

“不行,20分鐘,不然我真很難跟你講清楚。”

“好吧……”

“行,那進來吧,咱好好聊聊” 

一、我們講什么? 

我們講兩個東西: 

1、WebGL背后的工作原理是什么?

2、以Three.js為例,講述框架在背后扮演什么樣的角色? 

二、我們?yōu)槭裁匆私庠恚?/strong> 

我們假定你對WebGL已經(jīng)有一定了解,或者用Three.js做過了一些東西,這個時候,你可能碰到了這樣一些問題: 

1、很多東西還是做不出來,甚至沒有任何思路;

2、碰到bug無法解決,甚至沒有方向;

3、性能出現(xiàn)問題,完全不知道如何去優(yōu)化。

這個時候,我們需要了解更多。 

三、先了解一個基礎概念 

1、什么是矩陣?

簡單說來,矩陣用于坐標變換,如下圖: 

 

2、那它具體是怎么變換的呢,如下圖: 

 

3、舉個實例,將坐標平移2,如下圖: 

 

如果這時候,你還是沒有理解,沒有關系,你只需要知道,矩陣用于坐標變換。 

四、WebGL的工作原理 

4.1、WebGL API 

在了解一門新技術前,我們都會先看看它的開發(fā)文檔或者API。 

查看Canvas的繪圖API,我們會發(fā)現(xiàn)它能畫直線、矩形、圓、弧線、貝塞爾曲線。 

于是,我們看了看WebGL繪圖API,發(fā)現(xiàn): 

 

它只能會點、線、三角形?一定是我看錯了。 

沒有,你沒看錯。 

 

就算是這樣一個復雜的模型,也是一個個三角形畫出來的。 

4.2、WebGL繪制流程 

簡單說來,WebGL繪制過程包括以下三步: 

1、獲取頂點坐標

2、圖元裝配(即畫出一個個三角形)

3、光柵化(生成片元,即一個個像素點) 

 

接下來,我們分步講解每個步驟。 

4.2.1、獲取頂點坐標 

頂點坐標從何而來呢?一個立方體還好說,如果是一個機器人呢?

沒錯,我們不會一個一個寫這些坐標。

往往它來自三維軟件導出,或者是框架生成,如下圖: 

 

寫入緩存區(qū)是啥?

沒錯,為了簡化流程,之前我沒有介紹。

由于頂點數(shù)據(jù)往往成千上萬,在獲取到頂點坐標后,我們通常會將它存儲在顯存,即緩存區(qū)內,方便GPU更快讀取。 

4.2.2、圖元裝配 

我們已經(jīng)知道,圖元裝配就是由頂點生成一個個圖元(即三角形)。那這個過程是自動完成的嗎?答案是并非完全如此。 

為了使我們有更高的可控性,即自由控制頂點位置,WebGL把這個權力交給了我們,這就是可編程渲染管線(不用理解)。 

WebGL需要我們先處理頂點,那怎么處理呢?我們先看下圖: 

 

我們引入了一個新的名詞,叫“頂點著色器”,它由opengl es編寫,由javascript以字符串的形式定義并傳遞給GPU生成。 

比如如下就是一段頂點著色器代碼:  

  1. attribute vec4 position; 
  2. void main() { 
  3.   gl_Position = position;   

attribute修飾符用于聲明由瀏覽器(javascript)傳輸給頂點著色器的變量值;

position即我們定義的頂點坐標; 

gl_Position是一個內建的傳出變量。 

這段代碼什么也沒做,如果是繪制2d圖形,沒問題,但如果是繪制3d圖形,即傳入的頂點坐標是一個三維坐標,我們則需要轉換成屏幕坐標。 

比如:v(-0.5, 0.0, 1.0)轉換為p(0.2, -0.4),這個過程類似我們用相機拍照。 

4.2.2.1、頂點著色器處理流程 

回到剛才的話題,頂點著色器是如何處理頂點坐標的呢? 

 

如上圖,頂點著色器會先將坐標轉換完畢,然后由GPU進行圖元裝配,有多少頂點,這段頂點著色器程序就運行了多少次。 

你可能留意到,這時候頂點著色器變?yōu)椋?nbsp; 

  1. attribute vec4 position; 
  2. uniform mat4 matrix; 
  3. void main() { 
  4.   gl_Position = position * matrix;   
  5.  

 這就是應用了矩陣matrix,將三維世界坐標轉換成屏幕坐標,這個矩陣叫投影矩陣,由javascript傳入,至于這個matrix怎么生成,我們暫且不討論。 

4.2.3、光柵化 

和圖元裝配類似,光柵化也是可控的。 

 

在圖元生成完畢之后,我們需要給模型“上色”,而完成這部分工作的,則是運行在GPU的“片元著色器”來完成。 

它同樣是一段opengl es程序,模型看起來是什么質地(顏色、漫反射貼圖等)、燈光等由片元著色器來計算。 

如下是一段簡單的片元著色器代碼:

 

  1. precision mediump float;   
  2. void main(void) { 
  3.     gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); 
  4.  

 

gl_FragColor即輸出的顏色值。 

4.2.3.1、片元著色器處理流程 

片元著色器具體是如何控制顏色生成的呢? 

 

如上圖,頂點著色器是有多少頂點,運行了多少次,而片元著色器則是,生成多少片元(像素),運行多少次。 

4.3、WebGL的完整工作流程 

至此,實質上,WebGL經(jīng)歷了如下處理流程: 

1、準備數(shù)據(jù)階段 

在這個階段,我們需要提供頂點坐標、索引(三角形繪制順序)、uv(決定貼圖坐標)、法線(決定光照效果),以及各種矩陣(比如投影矩陣)。 

其中頂點數(shù)據(jù)存儲在緩存區(qū)(因為數(shù)量巨大),以修飾符attribute傳遞給頂點著色器; 

矩陣則以修飾符uniform傳遞給頂點著色器。 

2、生成頂點著色器 

根據(jù)我們需要,由Javascript定義一段頂點著色器(opengl es)程序的字符串,生成并且編譯成一段著色器程序傳遞給GPU。 

3、圖元裝配 

GPU根據(jù)頂點數(shù)量,挨個執(zhí)行頂點著色器程序,生成頂點最終的坐標,完成坐標轉換。 

4、生成片元著色器 

模型是什么顏色,看起來是什么質地,光照效果,陰影(流程較復雜,需要先渲染到紋理,可以先不關注),都在這個階段處理。 

5、光柵化 

能過片元著色器,我們確定好了每個片元的顏色,以及根據(jù)深度緩存區(qū)判斷哪些片元被擋住了,不需要渲染,最終將片元信息存儲到顏色緩存區(qū),最終完成整個渲染。 

 

五、Three.js究竟做了什么? 

我們知道,three.js幫我們完成了很多事情,但是它具體做了什么呢,他在整個流程中,扮演了什么角色呢? 

我們先簡單看一下,three.js參與的流程: 

 

黃色和綠色部分,都是three.js參與的部分,其中黃色是javascript部分,綠色是opengl es部分。 

我們發(fā)現(xiàn),能做的,three.js基本上都幫我們做了。 

  • 輔助我們導出了模型數(shù)據(jù);

  • 自動生成了各種矩陣;

  • 生成了頂點著色器;

  • 輔助我們生成材質,配置燈光;

  • 根據(jù)我們設置的材質生成了片元著色器。

  • 而且將webGL基于光柵化的2D API,封裝成了我們人類能看懂的 3D API。 

5.1、Three.js頂點處理流程 

從WebGL工作原理的章節(jié)中,我們已經(jīng)知道了頂點著色器會將三維世界坐標轉換成屏幕坐標,但實際上,坐標轉換不限于投影矩陣。 

如下圖: 

 

之前WebGL在圖元裝配之后的結果,由于我們認為模型是固定在坐標原點,并且相機在x軸和y軸坐標都是0,其實正常的結果是這樣的: 

 

5.1.1、模型矩陣 

 

現(xiàn)在,我們將模型順時針旋轉Math.PI/6,所有頂點位置肯定都變化了。  

  1. box.rotation.y = Math.PI/6; 

但是,如果我們直接將頂點位置用javascript計算出來,那性能會很低(頂點通常成千上萬),而且,這些數(shù)據(jù)也非常不利于維護。 

所以,我們用矩陣modelMatrix將這個旋轉信息記錄下來。 

5.1.2、視圖矩陣 

 

然后,我們將相機往上偏移30。 

 

  1. camera.position.y = 30; 

 

同理,我們用矩陣viewMatrix將移動信息記錄下來。 

5.1.3、投影矩陣 

 

這是我們之前介紹過的了,我們用projectMatrix記錄。 

5.1.4、應用矩陣 

然后,我們編寫頂點著色器: 

  1. gl_Position = position * modelMatrix * viewMatrix * projectionMatrix; 

這樣,我們就在GPU中,將最終頂點位置計算出來了。 

實際上,上面所有步驟,three.js都幫我們完成了。 

 

5.2、片元著色器處理流程 

我們已經(jīng)知道片元著色器負責處理材質、燈光等信息,但具體是怎么處理呢? 

如下圖: 

 

5.3、three.js完整運行流程: 

 

當我們選擇材質后,three.js會根據(jù)我們所選的材質,選擇對應的頂點著色器和片元著色器。 

three.js中已經(jīng)內置了我們常用著色器。 

責任編輯:龐桂玉 來源: 前端大全
相關推薦

2017-05-08 11:41:37

WebGLThree.js

2021-02-05 15:01:41

GitLinux命令

2016-06-01 09:19:08

開發(fā)3D游戲

2021-12-07 07:32:09

kafka架構原理

2024-10-30 10:06:51

2010-03-19 14:57:52

三層交換機

2012-06-14 13:22:35

JavaScript

2023-08-04 09:56:15

2010-02-05 14:06:36

Android Dev

2020-09-07 11:14:02

Vue異步更新

2021-06-09 10:29:23

Kafka架構組件

2021-04-09 08:54:14

Kafka源碼架構開發(fā)技術

2021-11-22 06:14:45

Three.js3D 渲染花瓣雨

2009-06-18 13:31:03

Spring工作原理

2009-08-14 13:19:23

2016-10-11 13:48:41

WebGLJavascriptWeb

2021-08-02 07:57:03

注冊Nacos源碼

2022-11-08 00:00:00

監(jiān)控系統(tǒng)Prometheus

2021-04-23 16:40:49

Three.js前端代碼

2019-11-29 09:30:37

Three.js3D前端
點贊
收藏

51CTO技術棧公眾號