THREE.JS入門教程(2)著色器-上
更新時間:2013年01月24日 10:47:05 作者:
Three.js是一個偉大的開源WebGL庫,WebGL允許JavaScript操作GPU,在瀏覽器端實現(xiàn)真正意義的3D,本文將介紹頂點著色器/片元著色器/著色器變量等等,感興趣的朋友可以了解下哦
譯序
Three.js是一個偉大的開源WebGL庫,WebGL允許JavaScript操作GPU,在瀏覽器端實現(xiàn)真正意義的3D。但是目前這項技術(shù)還處在發(fā)展階段,資料極為匱乏,愛好者學(xué)習(xí)基本要通過Demo源碼和Three.js本身的源碼來學(xué)習(xí)。
0.簡介
之前我已經(jīng)給出了一篇《開始使用Three.js》。如果你還沒有讀過,你可能需要去讀一下,本文的基礎(chǔ)是在那一篇教程的基礎(chǔ)上完成的。
我想討論一下著色器。在Three.js幫助你免去了很多麻煩之前,原生WebGL就很優(yōu)秀了。有的時候,你也許會想要完成一些特定的效果,或者想對呈現(xiàn)在你的屏幕上的東西鉆研得更深入一些,那么著色器一定會進入你的視野。如果你像我一樣,你也同樣希望實現(xiàn)一些比上一篇教程中的基礎(chǔ)更加有意思的東西。這篇教程中,我會講解Three.js的基礎(chǔ),這些基礎(chǔ)實際上為我們做了很多枯燥的工作。
在開始之前我還要說,這篇教程會有相當(dāng)多的篇幅在解釋著色器的代碼,之后會有一篇教程會在著色器代碼的基礎(chǔ)上前進一點,利用著色器去做點什么。這是因為著色器shaders第一眼看上去并不易懂,需要一些解釋。
1.兩種著色器
WebGL沒有固定的渲染管線,你無法直接使用一個黑盒子式的著色器(譯者注:上個世紀的顯卡基本都只支持固定渲染管線);WebGL提供的是可編程的管線,這種方式更強大但也更難理解和使用。長話短說,可編程渲染管線意味著編寫程序的人要自己負責(zé)獲取頂點并將它繪制在屏幕上了。著色器是渲染管線的一部分,有兩種著色器:
1.頂點著色器
2.片元著色器
你應(yīng)當(dāng)知道的是,這兩種著色器都完全運行在顯卡的GPU上,我們將需要它們處理的數(shù)據(jù)從CPU上卸下,裝到GPU上,減輕了CPU的復(fù)旦?,F(xiàn)代的GPU對著色器需要的調(diào)用的運算類型都做了大幅優(yōu)化,這樣做很值得。
2.頂點著色器
基元形狀,比如一個球體,是由頂點構(gòu)成的,是吧?頂點著色器被依次傳入這些頂點中的一個頂點,然后處理它。如何處理每個頂點是可以自由定制的,但頂點著色器有一個必做的事,就是為一個名為 gl_Position 的變量賦值,該變量是一個4維數(shù)組,表示該頂點最終在屏幕上的位置。這本身是個有意思的過程,因為我們實際上在談?wù)撊绾螌⒁粋€三維坐標(一個具有x、y、z值得頂點)轉(zhuǎn)化為,或者說投影到二維的屏幕上。謝天謝地,要是我們使用Three.js之類的工具,我們能夠如此方便地訪問到 gl_Position 。
3.片元著色器
現(xiàn)在我們有包含頂點的三維物體了,現(xiàn)在要將物體投影到二維屏幕上了,但顏色哪里去了?紋理和光照呢?這正是片元著色器要處理的。
和頂點著色器類似,片元著色器有一項必須完成的任務(wù):設(shè)置或消除變量 gl_FragColor ,另一個四維浮點變量,也就是片元點最終的顏色。什么是片元?想象一個具有三個頂點的三角形,片元就是經(jīng)過這三個頂點計算后的,所有在三角形內(nèi)部的點。因此,片元值由頂點的值內(nèi)插生成。如果一個頂點的顏色是紅色,相鄰頂點的顏色是藍色,那么我們可以觀測到顏色從紅色頂點附近漸變,由紅色變成紫色,最終在藍色頂點附近變成藍色。
4.著色器變量
說到著色器變量,有三種:Uniforma,Attributes和Varyings。當(dāng)我第一次聽到這三個詞語時,我很困惑,因為它們和我之前用到的東西完全不匹配。但現(xiàn)在,你可以這樣理解它們:
1.Uniforms變量既可以傳入頂點著色器,也可以傳入片元著色器,它們包含了哪些在整個渲染過程中保持不變的變量,比如,一個點光源的位置。
2.Attributes變量對應(yīng)于每個頂點,它們只可以傳入頂點著色器中,比如每個頂點都具有一個顏色。Attributes變量和頂點的關(guān)系是一一對應(yīng)的。
3.Varyings變量是在頂點著色器中定義,并且準備傳入給片元著色器的變量。為了確保這點,我們需要確保在兩個著色器中變量的類型和命名完全一致。一個經(jīng)典的應(yīng)用是法線向量,因為在計算光照的時候需要用到法線。
在后面一篇教程中,我會使用這三種變量,你也會學(xué)習(xí)到這三種變量如何真正應(yīng)用起來得。
現(xiàn)在,我們已經(jīng)談過了頂點著色器、片元著色器和三種著色器變量。是時候來看一個我們可以創(chuàng)建的最簡單的著色器了。
5.Hello World(譯者吐槽:能不能不要秀法語?。?/STRONG>
這兒有一個最簡單的頂點著色器:
/**
* 每個頂點坐標乘以模型視圖矩陣在乘以投影矩陣
* 獲得在二維屏幕上的坐標
*/
void main() {
gl_Position = projectionMatrix *
modelViewMatrix *
vec4(position,1.0);
}
一個最簡單的片元著色器:
/**
* 將任意一個像元色設(shè)置為粉紅
*/
void main() {
gl_FragColor = vec4(1.0, // R
0.0, // G
1.0, // B
1.0); // A
}
這就是全部了。如果現(xiàn)在直接運行的話,你就可以在屏幕上看到一個“無光”的粉紅色形體。不是很復(fù)雜,是嗎?
在頂點著色器中,我們通過Three.js傳入了一些uniforms變量。有兩個4×4的矩陣uniforms變量:模型視圖矩陣和投影矩陣。你并不需要太了解這兩個矩陣是怎么工作的。簡單地說,這兩個矩陣描述了三維點坐標如何投影成為二維屏幕上的坐標。
事實上,我只介紹了這兩段簡短的代碼段。Three.js在你自己的著色器代碼前已經(jīng)將它們加進來了,所以你不必擔(dān)心。實話說,Three.js還加了很多東西在你的代碼前面,比如光照數(shù)據(jù)、節(jié)點顏色和節(jié)點法向量等等。如果沒有Three.js你要親自創(chuàng)建并設(shè)置這些對象,真的。
6.使用著色器材質(zhì)
/**
* 假設(shè)我們可以使用JQuery
* 將著色器的代碼文本從DOM中抽取出來
*/
var vShader = $('vertexshader');
var fShader = $('fragmentshader');
var shaderMaterial =
new THREE.ShaderMaterial({
vertexShader: vShader.text(),
fragmentShader: fShader.text()
});
從這兒開始,Three.js將會編譯并運行你的著色器,將其連接在你創(chuàng)建的材質(zhì)上,材質(zhì)又依附于你創(chuàng)建的mesh上。它并沒有變得比真的更容易。也許是這樣吧,但我們在考慮瀏覽器3D編程,我想你應(yīng)該預(yù)期,這個話題是有一定復(fù)雜性的。
我們還可以像著色器材質(zhì)添加另外兩種屬性:uniforms和attributes。他們可以是向量、整數(shù)或者浮點數(shù),但是如我之前所說,uniforms變量在計算所有點的過程中保持不變,所以它們更加可能是單一的值,而attributes變量是對每個頂點而言的,所以他們應(yīng)當(dāng)是數(shù)組。在一個mesh中,attribute變量和頂點應(yīng)當(dāng)是一一對應(yīng)的。
7.小結(jié)
這篇教程就到這里了,實際上我已經(jīng)講得很多了,但是在許多方面我都只是一掠而過。在下一篇教程中我會提供一個復(fù)雜的著色器,通過它我將傳入一些attributes變量和uniforms變量來做一些模擬光照效果。
我將這篇教程的源碼打包了,你可以下載下來作為參考
Three.js是一個偉大的開源WebGL庫,WebGL允許JavaScript操作GPU,在瀏覽器端實現(xiàn)真正意義的3D。但是目前這項技術(shù)還處在發(fā)展階段,資料極為匱乏,愛好者學(xué)習(xí)基本要通過Demo源碼和Three.js本身的源碼來學(xué)習(xí)。
0.簡介
之前我已經(jīng)給出了一篇《開始使用Three.js》。如果你還沒有讀過,你可能需要去讀一下,本文的基礎(chǔ)是在那一篇教程的基礎(chǔ)上完成的。
我想討論一下著色器。在Three.js幫助你免去了很多麻煩之前,原生WebGL就很優(yōu)秀了。有的時候,你也許會想要完成一些特定的效果,或者想對呈現(xiàn)在你的屏幕上的東西鉆研得更深入一些,那么著色器一定會進入你的視野。如果你像我一樣,你也同樣希望實現(xiàn)一些比上一篇教程中的基礎(chǔ)更加有意思的東西。這篇教程中,我會講解Three.js的基礎(chǔ),這些基礎(chǔ)實際上為我們做了很多枯燥的工作。
在開始之前我還要說,這篇教程會有相當(dāng)多的篇幅在解釋著色器的代碼,之后會有一篇教程會在著色器代碼的基礎(chǔ)上前進一點,利用著色器去做點什么。這是因為著色器shaders第一眼看上去并不易懂,需要一些解釋。
1.兩種著色器
WebGL沒有固定的渲染管線,你無法直接使用一個黑盒子式的著色器(譯者注:上個世紀的顯卡基本都只支持固定渲染管線);WebGL提供的是可編程的管線,這種方式更強大但也更難理解和使用。長話短說,可編程渲染管線意味著編寫程序的人要自己負責(zé)獲取頂點并將它繪制在屏幕上了。著色器是渲染管線的一部分,有兩種著色器:
1.頂點著色器
2.片元著色器
你應(yīng)當(dāng)知道的是,這兩種著色器都完全運行在顯卡的GPU上,我們將需要它們處理的數(shù)據(jù)從CPU上卸下,裝到GPU上,減輕了CPU的復(fù)旦?,F(xiàn)代的GPU對著色器需要的調(diào)用的運算類型都做了大幅優(yōu)化,這樣做很值得。
2.頂點著色器
基元形狀,比如一個球體,是由頂點構(gòu)成的,是吧?頂點著色器被依次傳入這些頂點中的一個頂點,然后處理它。如何處理每個頂點是可以自由定制的,但頂點著色器有一個必做的事,就是為一個名為 gl_Position 的變量賦值,該變量是一個4維數(shù)組,表示該頂點最終在屏幕上的位置。這本身是個有意思的過程,因為我們實際上在談?wù)撊绾螌⒁粋€三維坐標(一個具有x、y、z值得頂點)轉(zhuǎn)化為,或者說投影到二維的屏幕上。謝天謝地,要是我們使用Three.js之類的工具,我們能夠如此方便地訪問到 gl_Position 。
3.片元著色器
現(xiàn)在我們有包含頂點的三維物體了,現(xiàn)在要將物體投影到二維屏幕上了,但顏色哪里去了?紋理和光照呢?這正是片元著色器要處理的。
和頂點著色器類似,片元著色器有一項必須完成的任務(wù):設(shè)置或消除變量 gl_FragColor ,另一個四維浮點變量,也就是片元點最終的顏色。什么是片元?想象一個具有三個頂點的三角形,片元就是經(jīng)過這三個頂點計算后的,所有在三角形內(nèi)部的點。因此,片元值由頂點的值內(nèi)插生成。如果一個頂點的顏色是紅色,相鄰頂點的顏色是藍色,那么我們可以觀測到顏色從紅色頂點附近漸變,由紅色變成紫色,最終在藍色頂點附近變成藍色。
4.著色器變量
說到著色器變量,有三種:Uniforma,Attributes和Varyings。當(dāng)我第一次聽到這三個詞語時,我很困惑,因為它們和我之前用到的東西完全不匹配。但現(xiàn)在,你可以這樣理解它們:
1.Uniforms變量既可以傳入頂點著色器,也可以傳入片元著色器,它們包含了哪些在整個渲染過程中保持不變的變量,比如,一個點光源的位置。
2.Attributes變量對應(yīng)于每個頂點,它們只可以傳入頂點著色器中,比如每個頂點都具有一個顏色。Attributes變量和頂點的關(guān)系是一一對應(yīng)的。
3.Varyings變量是在頂點著色器中定義,并且準備傳入給片元著色器的變量。為了確保這點,我們需要確保在兩個著色器中變量的類型和命名完全一致。一個經(jīng)典的應(yīng)用是法線向量,因為在計算光照的時候需要用到法線。
在后面一篇教程中,我會使用這三種變量,你也會學(xué)習(xí)到這三種變量如何真正應(yīng)用起來得。
現(xiàn)在,我們已經(jīng)談過了頂點著色器、片元著色器和三種著色器變量。是時候來看一個我們可以創(chuàng)建的最簡單的著色器了。
5.Hello World(譯者吐槽:能不能不要秀法語?。?/STRONG>
這兒有一個最簡單的頂點著色器:
復(fù)制代碼 代碼如下:
/**
* 每個頂點坐標乘以模型視圖矩陣在乘以投影矩陣
* 獲得在二維屏幕上的坐標
*/
void main() {
gl_Position = projectionMatrix *
modelViewMatrix *
vec4(position,1.0);
}
一個最簡單的片元著色器:
復(fù)制代碼 代碼如下:
/**
* 將任意一個像元色設(shè)置為粉紅
*/
void main() {
gl_FragColor = vec4(1.0, // R
0.0, // G
1.0, // B
1.0); // A
}
這就是全部了。如果現(xiàn)在直接運行的話,你就可以在屏幕上看到一個“無光”的粉紅色形體。不是很復(fù)雜,是嗎?
在頂點著色器中,我們通過Three.js傳入了一些uniforms變量。有兩個4×4的矩陣uniforms變量:模型視圖矩陣和投影矩陣。你并不需要太了解這兩個矩陣是怎么工作的。簡單地說,這兩個矩陣描述了三維點坐標如何投影成為二維屏幕上的坐標。
事實上,我只介紹了這兩段簡短的代碼段。Three.js在你自己的著色器代碼前已經(jīng)將它們加進來了,所以你不必擔(dān)心。實話說,Three.js還加了很多東西在你的代碼前面,比如光照數(shù)據(jù)、節(jié)點顏色和節(jié)點法向量等等。如果沒有Three.js你要親自創(chuàng)建并設(shè)置這些對象,真的。
6.使用著色器材質(zhì)
復(fù)制代碼 代碼如下:
/**
* 假設(shè)我們可以使用JQuery
* 將著色器的代碼文本從DOM中抽取出來
*/
var vShader = $('vertexshader');
var fShader = $('fragmentshader');
var shaderMaterial =
new THREE.ShaderMaterial({
vertexShader: vShader.text(),
fragmentShader: fShader.text()
});
從這兒開始,Three.js將會編譯并運行你的著色器,將其連接在你創(chuàng)建的材質(zhì)上,材質(zhì)又依附于你創(chuàng)建的mesh上。它并沒有變得比真的更容易。也許是這樣吧,但我們在考慮瀏覽器3D編程,我想你應(yīng)該預(yù)期,這個話題是有一定復(fù)雜性的。
我們還可以像著色器材質(zhì)添加另外兩種屬性:uniforms和attributes。他們可以是向量、整數(shù)或者浮點數(shù),但是如我之前所說,uniforms變量在計算所有點的過程中保持不變,所以它們更加可能是單一的值,而attributes變量是對每個頂點而言的,所以他們應(yīng)當(dāng)是數(shù)組。在一個mesh中,attribute變量和頂點應(yīng)當(dāng)是一一對應(yīng)的。
7.小結(jié)
這篇教程就到這里了,實際上我已經(jīng)講得很多了,但是在許多方面我都只是一掠而過。在下一篇教程中我會提供一個復(fù)雜的著色器,通過它我將傳入一些attributes變量和uniforms變量來做一些模擬光照效果。
我將這篇教程的源碼打包了,你可以下載下來作為參考
相關(guān)文章
JavaScript中用于生成隨機數(shù)的Math.random()方法
這篇文章主要介紹了JavaScript中用于生成隨機數(shù)的Math.random()方法,是JS入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下2015-06-06全選復(fù)選框JavaScript編寫小結(jié)(附代碼)
這篇文章主要介紹了全選”復(fù)選框JavaScript編寫,分別附上html和js代碼以供大家更深刻了解,具體操作步驟大家可查看下文的詳細講解,感興趣的小伙伴們可以參考一下。2017-08-08JavaScript數(shù)據(jù)結(jié)構(gòu)與算法之鏈表
鏈表就是線性表中針對順序存儲結(jié)構(gòu)的一種優(yōu)化手段,但是在javascript語言中由于數(shù)組的特殊性(自動更新引用位置),所以我們可以采用對象的方式做鏈表存儲的結(jié)構(gòu)2016-01-01Typescript中interface與type的相同點與不同點的詳細說明
這篇文章主要介紹了Typescript中interface與type的相同點與不同點,并配有實例說明,需要的朋友可以參考下2022-11-11javascript數(shù)組去重方法總結(jié)(推薦)
這篇文章主要介紹了javascript數(shù)組去重方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03