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物件是和頂點一一對應的,所以我們對球體的每一個頂點都有一個值,就像這樣:
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變數加入著色器材質中,同時也需要加入頂點著色器。先來看看頂點著色器:
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.小結
就是它了!你看到球體正在奇怪地脈動著。關於著色器,還有太多的內容沒有講到呢,但是我希望這篇教學能夠對你有一些幫助。現在,當你看到一些其他的著色器時,我希望你能夠理解它們,而且你應該有信心創建自己的著色器了!
和往常一樣,我將這一課的源碼打包了

JavaScript在現實世界中的應用包括服務器端編程、移動應用開發和物聯網控制:1.通過Node.js實現服務器端編程,適用於高並發請求處理。 2.通過ReactNative進行移動應用開發,支持跨平台部署。 3.通過Johnny-Five庫用於物聯網設備控制,適用於硬件交互。

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

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

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

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

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

Python更适合数据科学和机器学习,JavaScript更适合前端和全栈开发。1.Python以简洁语法和丰富库生态著称,适用于数据分析和Web开发。2.JavaScript是前端开发核心,Node.js支持服务器端编程,适用于全栈开发。

JavaScript不需要安裝,因為它已內置於現代瀏覽器中。你只需文本編輯器和瀏覽器即可開始使用。 1)在瀏覽器環境中,通過標籤嵌入HTML文件中運行。 2)在Node.js環境中,下載並安裝Node.js後,通過命令行運行JavaScript文件。


熱AI工具

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

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

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

MinGW - Minimalist GNU for Windows
這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

SAP NetWeaver Server Adapter for Eclipse
將Eclipse與SAP NetWeaver應用伺服器整合。

記事本++7.3.1
好用且免費的程式碼編輯器

Dreamweaver Mac版
視覺化網頁開發工具

SublimeText3 Linux新版
SublimeText3 Linux最新版