Three.js 後製特效 (Post‑Processing) 教學 – Bloom、Depth of Field、Motion Blur
簡介
在 3D 網頁應用中,光影與鏡頭效果往往是決定視覺品質的關鍵。即使模型、材質已經非常細緻,缺少後製特效仍會讓畫面顯得平板、缺乏層次感。Post‑Processing(後製特效)正是透過在渲染完成後對畫面做一次或多次的濾鏡運算,為場景加入光暈、景深、動態模糊等效果,讓作品瞬間升級為「專業級」的視覺體驗。
在 Three.js 生態系中,EffectComposer 與一系列 Pass(通道)提供了彈性極高的後製管線。本文將聚焦 Bloom、Depth of Field(景深)與 Motion Blur(運動模糊) 三大常見特效,說明概念、示範程式碼,並分享實務上常見的陷阱與最佳實踐,幫助初學者快速上手、進階開發者優化效能。
核心概念
1. 後製管線的基本組件
| 元件 | 功能說明 |
|---|---|
EffectComposer |
負責管理多個 Pass,將渲染結果依序傳遞、合成最終影像。 |
RenderPass |
首個 Pass,將 Three.js 場景渲染到緩衝區,供後續 Pass 使用。 |
ShaderPass / Pass |
以自訂或內建的 shader 進行影像處理,如模糊、顏色校正等。 |
RenderTarget |
離屏緩衝區,存放每一次 Pass 的輸出,避免直接寫回螢幕。 |
重點:後製特效不是在
WebGLRenderer直接完成,而是透過EffectComposer把渲染結果「再加工」一次或多次。
2. Bloom(光暈)
Bloom 會將亮部的光能向周圍擴散,模擬相機鏡頭或人眼在強光下的光暈。Three.js 官方提供 UnrealBloomPass,適合大多數需求。
2.1 主要參數
| 參數 | 說明 |
|---|---|
strength |
光暈強度。數值越大,光暈越明顯。 |
radius |
擴散半徑,控制光暈的範圍。 |
threshold |
亮度門檻,低於此值的像素不會產生光暈。 |
2.2 範例程式碼
// 基本設定
import * as THREE from 'three';
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer.js';
import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass.js';
import { UnrealBloomPass } from 'three/examples/jsm/postprocessing/UnrealBloomPass.js';
// 建立 renderer、scene、camera(此處略過)...
// 1. 建立 EffectComposer
const composer = new EffectComposer(renderer);
// 2. 加入 RenderPass(渲染場景本身)
composer.addPass(new RenderPass(scene, camera));
// 3. 設定 BloomPass
const bloomPass = new UnrealBloomPass(
new THREE.Vector2(window.innerWidth, window.innerHeight),
1.5, // strength
0.4, // radius
0.85 // threshold
);
composer.addPass(bloomPass);
// 4. 渲染循環
function animate() {
requestAnimationFrame(animate);
// 更新物件...
composer.render();
}
animate();
小技巧:若只想讓特定物件產生光暈,可使用 渲染層 (layers) 或 自訂遮罩 (mask),將不需要 Bloom 的物件排除。
3. Depth of Field(景深)
景深模擬相機聚焦點前後的模糊程度,使觀者的視線自然聚焦於關鍵區域。Three.js 常用 BokehPass 或 DOFPass(來自 postprocessing 套件)實作。
3.1 主要參數
| 參數 | 說明 |
|---|---|
focus |
聚焦距離(相機到聚焦點的距離)。 |
aperture |
光圈大小,光圈越大(數值越小)模糊越明顯。 |
maxblur |
最大模糊半徑,限制過度模糊。 |
3.2 範例程式碼(使用 BokehPass)
import { BokehPass } from 'three/examples/jsm/postprocessing/BokehPass.js';
// ...先前的 composer、renderPass 已建立
const bokehPass = new BokehPass(scene, camera, {
focus: 1.0, // 聚焦在 1 單位距離
aperture: 0.025, // 光圈
maxblur: 0.01, // 最大模糊半徑
width: window.innerWidth,
height: window.innerHeight
});
// 若需要先渲染一次以取得深度緩衝區
bokehPass.renderToScreen = true; // 最後一個 Pass 才需要渲染到螢幕
composer.addPass(bokehPass);
注意:
BokehPass需要深度緩衝區支援(renderer.getDepthTexture()),在建立WebGLRenderer時請設定depth: true。
4. Motion Blur(運動模糊)
Motion Blur 讓快速移動的物體產生拖尾感,提升畫面的真實感。Three.js 有兩種常見實作方式:
- 基於速度緩衝區的模糊(
ShaderPass+ 自訂速度貼圖) - 累積緩衝區 (Accumulation Buffer):將前幾幀畫面混合,產生簡易的模糊。
下面示範使用 ShaderPass 搭配 VelocityPass(來自 postprocessing 套件):
import { ShaderPass } from 'three/examples/jsm/postprocessing/ShaderPass.js';
import { VelocityPass } from 'three/examples/jsm/postprocessing/VelocityPass.js';
import { MotionBlurPass } from 'three/examples/jsm/postprocessing/MotionBlurPass.js';
// 1. VelocityPass 先算出每個像素的螢幕空間速度
const velocityPass = new VelocityPass(scene, camera);
composer.addPass(velocityPass);
// 2. MotionBlurPass 依速度貼圖產生模糊
const motionBlurPass = new MotionBlurPass({
blendFunction: THREE.AdditiveBlending,
intensity: 0.8 // 模糊強度
});
composer.addPass(motionBlurPass);
實務建議:若場景中有大量粒子或快速相機移動,累積緩衝區的方式較省資源;但若需要根據物件速度做精細控制,請使用速度緩衝區方案。
常見陷阱與最佳實踐
| 陷阱 | 說明 | 解決方式 |
|---|---|---|
| 效能急遽下降 | 多個 Pass 同時執行會導致 GPU 計算量翻倍。 | 只保留必要的特效,使用 setSize 動態調整解析度;在低階裝置上關閉 Bloom 或降低 radius。 |
| 深度緩衝區缺失 | BokehPass、DepthOfFieldPass 需要深度貼圖。 |
建立 WebGLRenderer({ antialias:true, depth:true }),或手動加入 depthTexture。 |
| 光暈洩漏到 UI | Bloom 會把 UI(HTML overlay)也渲染進緩衝區,產生不必要的光暈。 | 把 UI 放在 renderer.domElement 之上,或在 composer 前後分別渲染 3D 與 UI。 |
| 畫面抖動 | Motion Blur 使用累積緩衝區時,若相機或物件位置在每幀不夠平滑會出現抖動。 | 確保更新邏輯在 requestAnimationFrame 前完成,或使用時間插值 (interpolation)。 |
| 通道順序錯誤 | Pass 的加入順序會影響最終結果,例如 Bloom 必須在景深之前。 | 依需求測試,常見順序:RenderPass → BloomPass → DepthOfFieldPass → MotionBlurPass。 |
最佳實踐:
- 分辨率縮放:對非核心特效使用
composer.setSize(width/2, height/2),再上采樣回螢幕,能顯著降低 GPU 負擔。 - 層級控制:利用
camera.layers與object.layers把需要 Bloom 的物件放在獨立層,搭配MaskPass只對該層做後製。 - 自適應品質:根據
navigator.deviceMemory或performance.now()的幀率,動態調整特效參數(如strength、maxblur)。
實際應用場景
| 場景 | 推薦特效組合 | 為何使用 |
|---|---|---|
| 科幻射擊遊戲 | Bloom + Motion Blur | 光暈強化激光、子彈的光線感;運動模糊提升彈道速度感。 |
| 寫實建築漫遊 | Depth of Field + subtle Bloom | 景深讓觀者聚焦在入口或焦點建築,柔和光暈提升光線散射真實感。 |
| 音樂視覺化 | Bloom + Motion Blur (high intensity) | 音浪與粒子在節奏中快速移動,模糊與光暈創造動感氛圍。 |
| 教育模擬 (如顯微鏡) | Depth of Field | 只聚焦在樣本的特定層面,其他區域自然模糊,模擬實驗室光學效果。 |
| 虛擬展覽 | 低強度 Bloom + optional DOF | 提升展品的光澤感,同時保持整體流暢度,避免過度特效影響觀展體驗。 |
總結
Three.js 的 Post‑Processing 為 3D 網頁應用提供了「相機」與「鏡頭」層面的視覺調整。
- Bloom 讓亮部光暈自然擴散,提升光源與金屬材質的視覺衝擊。
- Depth of Field 透過聚焦與模糊,導引使用者的視線,營造寫實或戲劇化的氛圍。
- Motion Blur 為快速移動的物件或相機增添動態感,使畫面更具臨場感。
掌握 EffectComposer、Pass 的組合與參數調校,並留意效能、深度緩衝區與渲染順序的細節,就能在不同的專案中靈活運用這些特效,為你的 Three.js 作品增添專業級的視覺魅力。祝你玩得開心,創作出令人驚豔的 Web 3D 體驗!