從零開始學習three.js(18):一文詳解three.js中的著色器Shader

在WebGL和Three.js的3D圖形渲染中,著色器(Shader) 是實現復雜視覺效果的核心工具。通過編寫自定義的著色器代碼,開發者可以直接操作GPU,實現從基礎顏色渲染到動態光照、粒子效果等高級圖形技術。本文將深入解析Three.js中著色器的核心概念、實現原理及實戰應用,并結合代碼示例幫助讀者全面掌握這一關鍵技術。

核心特點??:


一、著色器基礎與分類

1.1 頂點著色器(Vertex Shader)

頂點著色器負責處理幾何體的每個頂點,主要功能包括:

  • 頂點位置變換:將模型空間坐標轉換為屏幕空間坐標(通過 gl_Position 輸出)
  • 頂點屬性計算:如法線變換、紋理坐標傳遞等
void main() {gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}

說明projectionMatrix(投影矩陣)、modelViewMatrix(模型視圖矩陣)由Three.js自動注入,position是頂點的原始坐標。

1.2 片元著色器(Fragment Shader)

片元著色器決定每個像素的最終顏色,通過 gl_FragColor 輸出:

void main() {gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); // 紅色
}

特性:顏色支持動態計算,如基于光照模型、紋理采樣等。

1.3 著色器材質類型

Three.js提供兩種自定義著色器材質:

  • ??ShaderMaterial??:簡化版材質,內置常用變量(如modelViewMatrixprojectionMatrix),適合快速開發。

  • ??RawShaderMaterial??:需手動聲明所有變量(如attributeuniform),靈活性更高,適合深度優化。

??示例代碼:創建基礎著色器材質??

const material = new THREE.ShaderMaterial({  vertexShader: vertexShaderCode,  fragmentShader: fragmentShaderCode,  uniforms: {  time: { value: 0 },  color: { value: new THREE.Color(0xff0000) }  }  
});  

二、著色器變量類型

2.1 Uniforms

  • 全局常量:所有頂點/片元共享同一值(如時間、光源位置)
  • 傳遞方式:通過 ShaderMaterialuniforms 屬性設置
const material = new THREE.ShaderMaterial({uniforms: {uTime: { value: 0 },uTexture: { value: new THREE.TextureLoader().load("texture.png") }}
});

在著色器中聲明uniform float uTime;

2.2 Attributes

  • 頂點屬性:每個頂點獨有的數據(如位置、顏色、法線)
  • 典型應用:動態頂點動畫(如波浪效果)
geometry.setAttribute('displacement', new THREE.BufferAttribute(displacementArray, 1));

在頂點著色器中訪問attribute float displacement;

2.3 Varyings

  • 插值變量:從頂點著色器向片元著色器傳遞數據(如UV坐標、顏色插值)
// 頂點著色器
varying vec2 vUv;
void main() {vUv = uv;// ...
}// 片元著色器
varying vec2 vUv;
void main() {vec4 color = texture2D(uTexture, vUv);
}

注意:變量名需在兩者中保持一致。


三、矩陣變換與坐標系統

3.1 核心矩陣解析

  • 模型矩陣(modelMatrix) :幾何體的旋轉、平移、縮放變換
  • 視圖矩陣(viewMatrix) :相機的觀察變換(等同于相機世界矩陣的逆矩陣)
  • 投影矩陣(projectionMatrix) :3D到2D的投影(如透視投影)

3.2 矩陣乘法順序

頂點變換遵循 “右乘”順序,確保坐標正確轉換:

gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(position, 1.0);

原理:從模型空間→世界空間→相機空間→裁剪空間逐步變換。


四、實戰案例:動態波紋效果

4.1 著色器代碼實現

頂點著色器(傳遞UV坐標):

varying vec2 vUv;
void main() {vUv = uv;gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}

片元著色器(動態波紋計算):

uniform float uTime;
varying vec2 vUv;void main() {float ripple = sin(length(vUv - 0.5) * 10.0 - uTime * 2.0);float opacity = smoothstep(0.0, 0.2, abs(ripple));gl_FragColor = vec4(0.2, 0.5, 1.0, opacity);
}

4.2 JavaScript端配置

const material = new THREE.ShaderMaterial({uniforms: {uTime: { value: 0 }},vertexShader: vertexShaderCode,fragmentShader: fragmentShaderCode,transparent: true
});// 動畫循環中更新Uniform
function animate() {material.uniforms.uTime.value += 0.01;requestAnimationFrame(animate);
}

效果:實現以中心向外擴散的藍色波紋。


五、高級技巧與優化

5.1 性能優化策略

  1. 減少分支語句:GPU不擅長動態分支,可用 mix()step() 替代 if-else
  2. 向量化運算:優先使用 vec3/vec4 代替多個 float 計算
  3. 紋理壓縮:使用Mipmap和紋理圖集減少采樣開銷

5.2 常見問題排查

  • 變量未聲明:檢查Three.js版本是否支持特定語法(如 #version 300 es
  • 精度問題:在移動端明確指定精度(precision mediump float;
  • 矩陣順序錯誤:確保模型→視圖→投影的乘法順序正確

六、擴展應用:后期處理通道

通過 EffectComposerShaderPass 實現屏幕后處理:

import { EffectComposer, ShaderPass } from 'three/examples/jsm/postprocessing';const composer = new EffectComposer(renderer);
composer.addPass(new RenderPass(scene, camera));const customPass = new ShaderPass(customShaderMaterial);
composer.addPass(customPass);

典型效果:模糊、Bloom光效、顏色校正等。


結語

Three.js著色器為開發者打開了高性能圖形編程的大門。通過深入理解GLSL語法、矩陣變換和變量傳遞機制,可以創造出從基礎顏色變化到復雜物理模擬的全方位視覺效果。建議通過Shadertoy平臺進行實時演練,結合Three.js文檔探索更多可能性。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/83532.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/83532.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/83532.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Python函數庫調用實戰:以數據分析為例

一、引言 Python之所以在編程領域廣受歡迎,很大程度上得益于其豐富且強大的函數庫。這些函數庫涵蓋了從數據分析、科學計算到Web開發、機器學習等眾多領域,極大地提高了開發效率。本文將以數據分析為例,介紹如何調用Python的一些常用函數庫。…

shell腳本之條件判斷,循環控制,exit詳解

if條件語句的語法及案例 一、基本語法結構 1. 單條件判斷 if [ 條件 ]; then命令1命令2... fi2. 雙分支(if-else) if [ 條件 ]; then條件為真時執行的命令 else條件為假時執行的命令 fi3. 多分支(if-elif-else) if [ 條件1 ]…

現代 Web 自動化測試框架對比:Playwright 與 Selenium 的深度剖析

現代 Web 自動化測試框架對比:Playwright 與 Selenium 的深度剖析 摘要:本文對 Playwright 與 Selenium 在開發適配性、使用難度、場景適用性及性能表現等方面進行了全面深入的對比分析。通過詳細的技術實現細節闡述與實測數據支撐,為開發者…

系統架構設計(十):結構化編程

定義 結構化編程是一種遵循清晰邏輯結構、避免使用 goto 的編程方法。它強調使用有限的三種基本控制結構來組織程序,提高程序的可讀性、可維護性和可測試性。 它是現代程序設計的基礎,被廣泛應用于命令式語言(如 C、Pascal、Java&#xff0…

TC3xx學習筆記-UCB BMHD使用詳解(二)

文章目錄 前言Confirmation的定義Dual UCB: Confirmation StatesDual UCB: Errored State or ECC Error in the UCB Confirmation CodesECC Error in the UCB ContentDual Password UCB ORIG and COPY Re-programming UCB_BMHDx_ORIG and UCB_BMHDx_COPY (x 0-3)BMHD Protecti…

OTA與boot loader

OTA指的是無線升級,通常用于更新設備的固件或軟件,用戶不用手動操作,非常方便。而bootloader是啟動時加載操作系統的程序,負責硬件初始化和啟動流程。 首先,OTA是如何通過bootloader工作的。OTA下載更新包后&#xff0…

實驗六:FPGA序列檢測器實驗

FPGA序列檢測器實驗(遠程實驗系統) 文章目錄 FPGA序列檢測器實驗(遠程實驗系統)一、數字電路基礎知識1. 時鐘與同步2. 按鍵消抖原理代碼講解:分頻與消抖3. 有限狀態機(FSM)設計代碼講解:狀態機編碼與轉移4. 邊沿檢測與信號同步5. 模塊化設計二、實驗數字電路整體思想三…

jenkins部署

開發者將代碼push到git運維人員通過jenkins部署,自動到git上pull代碼通過maven構建成jar包,并結合dockerfile打包成鏡像,push docker鏡像到docker registry通過k8s發起 發布/更新 服務 操作 通過Jenkins部署,自動到Git上PULL代碼 …

BBR 的 buffer 動力學觀感

這周很忙,今天還加了一天班,但還是抽空實現了五一在安徽涇縣山區喝著一壺酒寫的 BBR ProbeRTT 的想法,沒多少行代碼,它真就消除了帶寬鋸齒,皮了個鞋👞,昨天我還在群里說了今天再說說 BBR 的&…

第9講、深入理解Scaled Dot-Product Attention

Scaled Dot-Product Attention是Transformer架構的核心組件,也是現代深度學習中最重要的注意力機制之一。本文將從原理、實現和應用三個方面深入剖析這一機制。 1. 基本原理 Scaled Dot-Product Attention的本質是一種加權求和機制,通過計算查詢(Query…

el-tree結合checkbox實現數據回顯

組件代碼 <el-tree:data"vertiList"show-checkboxnode-key"id":props"defaultProps"ref"treeRefx"class"custom-tree"check-change"handleCheckChange"> </el-tree>獲取選擇的節點 handleCheckChan…

OpenResty 深度解析:構建高性能 Web 服務的終極方案

引言 openresty是什么&#xff1f;在我個人對它的理解來看相當于嵌入了lua的nginx; 我們在nginx中嵌入lua是為了不需要再重新編譯,我們只需要重新修改lua腳本,隨后重啟即可; 一.lua指令序列 我們分別從初始化階段&#xff0c;重寫/訪問階段&#xff0c;內容階段&#xff0c;日志…

多商戶商城系統源碼解析:開發直播電商APP的技術底層實戰詳解

隨著直播電商的火爆&#xff0c;越來越多的創業者和企業都在尋求打造自己的多商戶商城系統&#xff0c;以實現“人、貨、場”三者的深度融合。然而&#xff0c;從一個簡單的電商平臺到一個功能完善的直播電商APP&#xff0c;其技術底層架構和實現過程并非一蹴而就。本文將從架構…

桌面端進程通信

以下是關于 Electron 桌面端進程通信的基本知識點總結: 一、Electron 進程模型基礎 1. 進程類型與職責 進程類型職責權限主進程(Main)創建窗口、系統級操作、IPC中樞完全Node.js訪問權限渲染進程(Renderer)展示Web內容、UI交互默認受限(可配置開啟Node.js)預加載腳本(Prelo…

openEuler24.03 LTS下安裝MySQL8.0.42

目錄 前提步驟 刪除原有mysql及maridb數據庫 安裝MySQL 啟動MySQL 啟動查看MySQL狀態 設置MySQL開機自啟動 查看登錄密碼 登錄MySQL 修改密碼及支持遠程連接 遠程連接MySQL 前提步驟 擁有openEuler24.03 LTS環境&#xff0c;可參考&#xff1a;Vmware下安裝openEule…

idea 保證舊版本配置的同時,如何從低版本升到高版本

文章目錄 前言idea 保證舊版本配置的同時,如何從低版本升到高版本1. 備份項目2. 下載最新的idea3. 安裝安裝包4. 導入idea2019舊配置5. 驗證前言 如果您覺得有用的話,記得給博主點個贊,評論,收藏一鍵三連啊,寫作不易啊^ _ ^。 ??而且聽說點贊的人每天的運氣都不會太差,…

填坑記: 古董項目Apache POI 依賴異常排除

當你看到NoSuchMethodError的時候&#xff0c;不要慌&#xff0c;深呼吸&#xff0c;這可能只是JAR包版本的問題… 引子&#xff1a;一個平靜的周二下午 那是一個看似平常的周二下午&#xff0c;系統運行良好&#xff0c;開發團隊在有條不紊地推進著新功能的開發。突然&#x…

CAPL Class: TcpSocket (此類用于實現 TCP 網絡通信 )

目錄 Class: TcpSocketacceptopenclosebindconnectgetLastSocketErrorgetLastSocketErrorAsStringlistenreceivesendsetSocketOptionshutdown函數調用的基本流程服務器端的基本流程客戶端的基本流程Class: TcpSocket學習筆記。來自CANoe幫助文檔。 Class: TcpSocket accept /…

微信小程序的開發及問題解決

HttpClient 測試例子 SpringBootTest public class HttpClientTest {/*** 測試通過httpclient發送get方式的請求*/Testpublic void testGET() throws IOException {//創建httpclient對象CloseableHttpClient httpClient HttpClients.createDefault();//創建請求對象HttpGet ht…

foreach中使用await的問題

目錄 1.說明 2.示例 3.解決方案 1.說明 在foreach中調用異步方法&#xff0c;即使使用了await&#xff0c;不會依次執行每個異步任務&#xff0c;也就是說Array.prototype.forEach不會等待 Promise 完成&#xff0c;即使你在回調函數中返回一個 Promise&#xff0c;forEach …