首頁 web前端 js教程 THREE.JS入門教學(3)著色器-下_基礎知識

THREE.JS入門教學(3)著色器-下_基礎知識

May 16, 2016 pm 05:43 PM

譯序
Three.js是一個很棒的開源WebGL函式庫,WebGL允許JavaScript操作GPU,在瀏覽器端實現真正意義的3D。但目前這項技術還在發展階段,資料極為匱乏,愛好者學習基本上要透過Demo源碼和Three.js本身的源碼來學習。

.簡介
這是WebGL著色器教程的後半部分,如果你沒看過前一篇,閱讀這篇教程可能會使你感到困惑,建議你翻閱前面的教學。

上一篇結束的時候,我們在螢幕中央畫了一個好看的粉紅色的球體。現在我要開始創造一些更有意思的東西了。

在這篇教學中,我們會先花點時間加入一個動畫循環,然後是頂點attributes變數和一個uniform變數。我們還要加一些varying變量,這樣頂點著色器就可以傳遞訊息到片元著色器了。最終的結果是哪個粉紅色的球體會從頂部開始向兩側“點燃”,然後作有規律的運動。這有一點迷幻,但是會幫助你對著色器中的三種變數有更好的了解:他們互相聯繫,實現了整個集合體。當然我們會在Three.js的框架中做這些事。
1.模擬光照
讓我們更新顏色吧,這樣球體看起來就不會是個扁平晦暗的圓了。如果我們想看看Three.js是怎麼處理光照的,我敢肯定你會發現這比我們需要的要複雜得多,所以我們先模擬光照吧。你應該瀏覽一下Three.js中那些奇妙的著色器,還有一些來自最近的一個 Chris Milk 和 Google, Rome 的WebGL專案。
回到著色器,我們要更新頂點著色器來傳遞頂點的法向量到片元著色器。利用一個varying變數:
複製程式碼 程式碼如下:

/// 建立一個變數,頂點著色器和片元著色器都包含了該變數
varying vec3 vNormal;
void main() {
// 將vNormal設為normal,後者是Three.js建立並傳遞給著色器的attribute變數
vNormal = normal;
gl_Position = projectionMatrix *
modelViewMatrix *
vec4(position, 1.0);
}
vec4(position, 1.0);
}
複製程式碼 程式碼如下:

// 和頂點著色器中相同的變數vNormal
varying vec3 vNormal;
void main() {
// 定義光線向量
vec3 light = vec3(0.5,0.2,1.0);
// 確保其歸一化
light = normalize(light);
// 計算光線向量和法線向量的點積,如果點積小於0(即光線無法照到),就設為0
float dProd = max(0.0, dot(vNormal, light));
// 填充片元顏色
gl_FragColor = vec4(dProd, // R
dProd, // G
dProd, // B
1.0) ; // A
}

使用點積的原因是:兩個向量的點積顯示他們有多麼「相似」。如果兩個向量都是歸一化的,而且他們的方向一模一樣,點積的值就是1;如果兩個向量的方向剛好完全相反,點積的值就是-1。我們所做的就是把點積的值拿來作用到光纖上,所以如果這個點在球體的右上方,點積的值就是1,也就是完全照亮了;而在另一邊的點,得到的點積值接近0,甚至到了-1。我們將獲得的任何負值都設為0。當你將資料傳入之後,你會看到最基本的光照效果了。

下面是什麼?我們會將頂點的座標摻和進來。
2.Attribut變數
接下來我要透過Attribute變數為每個頂點傳遞一個隨機數,而這個隨機數用來將頂點沿著法線向量推出去一段距離。新的結果有點像是怪異的不規則物體,每次刷新頁面物體都會隨機變化。現在,他還不會動(後面我會讓他動起來),但是幾次刷新就可以很好地觀察到,他的形狀是隨機的。
讓我們開始為頂點著色器加入attribute變數:
複製程式碼 程式碼如下:

attribute float displacement;
varying vec3 vNormal;
void main() {
vNormal = normal;
// 將隨機數displacement轉換為三維向量,這樣就可以轉換為和維向量法線相乘了
vec3 newPosition = position
normal * vec3(displacement);
gl_Position = projectionMatrix *
modelViewMatrix *
vec4(newPectionMatrix *

你看到什麼都沒變,因為attribute變數displacement還沒被設定你,所以著色器就使用了0作為預設值。這時displacement還沒起作用,但我們馬上就要在著色器材質中加上attribute變數了,然後Three.js就會自動地把它們綁在一起運行了。

同時也要注意這樣一個事實,我將更新後的位置指定給了一個新的三維向量變量,因為原來的位置變量position,就像所有的attribute變量一樣,都是只讀的。

3.更新著色器材質
現在我們來更新著色器材質,傳入一些東西給attribute物件displacement。記住,attribute物件是和頂點一一對應的,所以我們對球體的每一個頂點都有一個值,就像這樣:

複製程式碼 程式碼如下:
var attributes = {
displacement: {
type: 'f', // 浮點數
value: [] //空數組
}
};
var vShader = $('#vertexshader');
var fShader = $('#fragmentshader');
// 建立一個包含attribute屬性的著色器材質
var shaderMaterial =
new THREE.MeshShaderMaterial({
attributes: attributes,
vertexShader: vShader.text(),
fragmentShader: fragment: vShader.text(),
fragmentShader> );
// 填入displacement隨機數
var verts = sphere.geometry.vertices;
var values = attributes.displacement.value;
for(var v = 0; v values.push(Math.random() * 30);
}


這樣,就可以看到一個變形的球體了。最Cool的是:所有這些變形都是在GPU中完成的。

4.動起來
要讓這東西動起來,該怎麼做?好吧,應該要做這兩件事。 一個uniform變數amplitude,在每一幀控制displacement實際上造成了多少位移。我們可以使用正弦或餘弦函數來在每一幀中產生它,因為這兩個函數的取值範圍從-1到1。
一個幀循環。

我們需要將這個uniform變數加入著色器材質中,同時也需要加入頂點著色器。先來看看頂點著色器:


複製程式碼 程式碼如下:
uniform float amplitude; 🎜>attribute float displacement;
varying vec3 vNormal;
void main() {
vNormal = normal;
// 將displacement乘以amplitude,當我們在每一幀中都平滑改變amplitude ,畫面就動起來了
vec3 newPosition =
position
normal *
vec3(displacement *
amplitude);
gl_Position = projectionMatrix }


然後更新著色器材質:



複製程式碼
複製程式碼複製程式碼


複製程式碼



複製程式碼



複製程式碼



複製程式碼


複製程式碼



複製碼> 程式碼如下:} ; var vShader = $('#vertexshader'); var fShader = $('#fragmentshader'); // 建立最終的著色器材質var shaderMaterial = new THREE.MeshShaderMaterial({ uniforms: uniforms, attributes: attributes, vertexShader: vShader.text(), fragmentShader: fShader.text() ); 🎜> 我們的著色器也已經就緒了。但我們好像又倒退了一步,螢幕中又只剩下光滑的球了。別擔心,這是因為amplitude值設為0,因為我們將amplitude乘以了displacement,所以現在看不到任何變化。我們還沒設定循環呢,所以amplitude只可能是0. 在我們的JavaScript中,需要將渲染過程打包成一個函數,然後用requestAnimationFrame去呼叫函數。在這個函數裡,我們更新uniform(譯者註:即amplitude)的值。 複製程式碼 程式碼如下:

var frame = 0;
function update() {
// amplitude來自於frame的正弦值
uniforms.amplitude.value =
Math.sin(>uniforms.amplitude.value =
Math.sin(frame);
// 更新全域變數frame
frame = 0.1;
renderer.render(scene, camera);
// 指定下次螢幕刷新時,呼叫update
requestAnimFrame(update);
}
requestAnimFrame(update);

5.小結

就是它了!你看到球體正在奇怪地脈動著。關於著色器,還有太多的內容沒有講到呢,但是我希望這篇教學能夠對你有一些幫助。現在,當你看到一些其他的著色器時,我希望你能夠理解它們,而且你應該有信心創建自己的著色器了!
和往常一樣,我將這一課的源碼打包了
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1660
14
CakePHP 教程
1416
52
Laravel 教程
1310
25
PHP教程
1260
29
C# 教程
1233
24
神秘的JavaScript:它的作用以及為什麼重要 神秘的JavaScript:它的作用以及為什麼重要 Apr 09, 2025 am 12:07 AM

JavaScript是現代Web開發的基石,它的主要功能包括事件驅動編程、動態內容生成和異步編程。 1)事件驅動編程允許網頁根據用戶操作動態變化。 2)動態內容生成使得頁面內容可以根據條件調整。 3)異步編程確保用戶界面不被阻塞。 JavaScript廣泛應用於網頁交互、單頁面應用和服務器端開發,極大地提升了用戶體驗和跨平台開發的靈活性。

JavaScript的演變:當前的趨勢和未來前景 JavaScript的演變:當前的趨勢和未來前景 Apr 10, 2025 am 09:33 AM

JavaScript的最新趨勢包括TypeScript的崛起、現代框架和庫的流行以及WebAssembly的應用。未來前景涵蓋更強大的類型系統、服務器端JavaScript的發展、人工智能和機器學習的擴展以及物聯網和邊緣計算的潛力。

JavaScript引擎:比較實施 JavaScript引擎:比較實施 Apr 13, 2025 am 12:05 AM

不同JavaScript引擎在解析和執行JavaScript代碼時,效果會有所不同,因為每個引擎的實現原理和優化策略各有差異。 1.詞法分析:將源碼轉換為詞法單元。 2.語法分析:生成抽象語法樹。 3.優化和編譯:通過JIT編譯器生成機器碼。 4.執行:運行機器碼。 V8引擎通過即時編譯和隱藏類優化,SpiderMonkey使用類型推斷系統,導致在相同代碼上的性能表現不同。

JavaScript:探索網絡語言的多功能性 JavaScript:探索網絡語言的多功能性 Apr 11, 2025 am 12:01 AM

JavaScript是現代Web開發的核心語言,因其多樣性和靈活性而廣泛應用。 1)前端開發:通過DOM操作和現代框架(如React、Vue.js、Angular)構建動態網頁和單頁面應用。 2)服務器端開發:Node.js利用非阻塞I/O模型處理高並發和實時應用。 3)移動和桌面應用開發:通過ReactNative和Electron實現跨平台開發,提高開發效率。

如何使用Next.js(前端集成)構建多租戶SaaS應用程序 如何使用Next.js(前端集成)構建多租戶SaaS應用程序 Apr 11, 2025 am 08:22 AM

本文展示了與許可證確保的後端的前端集成,並使用Next.js構建功能性Edtech SaaS應用程序。 前端獲取用戶權限以控制UI的可見性並確保API要求遵守角色庫

Python vs. JavaScript:學習曲線和易用性 Python vs. JavaScript:學習曲線和易用性 Apr 16, 2025 am 12:12 AM

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。

從C/C到JavaScript:所有工作方式 從C/C到JavaScript:所有工作方式 Apr 14, 2025 am 12:05 AM

從C/C 轉向JavaScript需要適應動態類型、垃圾回收和異步編程等特點。 1)C/C 是靜態類型語言,需手動管理內存,而JavaScript是動態類型,垃圾回收自動處理。 2)C/C 需編譯成機器碼,JavaScript則為解釋型語言。 3)JavaScript引入閉包、原型鍊和Promise等概念,增強了靈活性和異步編程能力。

使用Next.js(後端集成)構建多租戶SaaS應用程序 使用Next.js(後端集成)構建多租戶SaaS應用程序 Apr 11, 2025 am 08:23 AM

我使用您的日常技術工具構建了功能性的多租戶SaaS應用程序(一個Edtech應用程序),您可以做同樣的事情。 首先,什麼是多租戶SaaS應用程序? 多租戶SaaS應用程序可讓您從唱歌中為多個客戶提供服務

See all articles