Three.js
單元:開發環境與基本設置
主題:建立渲染器(WebGLRenderer)
簡介
在使用 Three.js 建立 3D 網頁應用時,最先要面對的就是「渲染器」的設定。渲染器負責把三維場景(Scene)與相機(Camera)轉換成瀏覽器可以顯示的 2D 圖像,核心就是 THREE.WebGLRenderer。如果渲染器的建立與配置不當,畫面可能會卡頓、顏色失真,甚至根本無法渲染。
本篇文章將一步一步說明如何 正確建立與調整 WebGLRenderer,並提供多個實用範例、常見陷阱與最佳實踐,讓讀者在開發過程中能快速上手、避免踩雷,最終打造出流暢且具備現代感的 3D 互動體驗。
核心概念
1. 為什麼選擇 WebGLRenderer?
Three.js 同時支援 WebGLRenderer、CanvasRenderer、SVGRenderer 等多種渲染器。
- WebGLRenderer:直接呼叫瀏覽器內建的 WebGL API,效能最高,支援光源、陰影、後期特效等。
- CanvasRenderer / SVGRenderer:僅在舊版瀏覽器或特定需求下使用,功能受限。
結論:除非有特殊相容性需求,開發新專案時幾乎都會使用
WebGLRenderer。
2. 基本建立流程
// 1️⃣ 匯入 Three.js(以 ES6 模組為例)
import * as THREE from 'three';
// 2️⃣ 建立渲染器實例
const renderer = new THREE.WebGLRenderer({
antialias: true, // 開啟抗鋸齒,使邊緣更平滑
alpha: true // 允許背景透明(可在 CSS 中設定顏色)
});
// 3️⃣ 設定渲染尺寸
renderer.setSize(window.innerWidth, window.innerHeight);
// 4️⃣ 把渲染器的 canvas 加入 DOM
document.body.appendChild(renderer.domElement);
小技巧:
renderer.domElement就是<canvas>元素,若要自訂樣式,只需操作這個 DOM 節點即可。
3. 重要屬性與方法
| 屬性 / 方法 | 功能說明 | 常見設定值 |
|---|---|---|
antialias |
是否開啟抗鋸齒 | true(預設關閉) |
alpha |
背景是否透明 | true / false |
setPixelRatio() |
調整 DPI,避免 Retina 螢幕顯示模糊 | window.devicePixelRatio |
setSize(width, height, updateStyle?) |
設定畫布寬高,updateStyle 為 true 時同時更新 CSS 大小 |
window.innerWidth, window.innerHeight |
outputEncoding |
色彩編碼,THREE.sRGBEncoding 可提升顏色準確度 |
THREE.sRGBEncoding |
shadowMap.enabled |
是否啟用陰影渲染 | true / false |
toneMapping |
色調映射,常用 THREE.ACESFilmicToneMapping |
THREE.NoToneMapping(預設) |
程式碼範例
以下提供 五個 常見且實用的範例,示範如何在不同情境下設定 WebGLRenderer。每段程式碼皆附有說明註解,方便直接貼上測試。
範例 1️⃣ 基本渲染器 + 抗鋸齒
import * as THREE from 'three';
// 建立渲染器,開啟抗鋸齒
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 後續:scene、camera、mesh...
說明:抗鋸齒對於曲線或文字模型非常重要,能減少「鋸齒狀」的視覺噪點。
範例 2️⃣ 支援 Retina 螢幕
import * as THREE from 'three';
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(window.devicePixelRatio); // ★ 重要
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
重點:
setPixelRatio會把畫布的實際像素乘上裝置的 DPI,確保在高解析度螢幕上不會顯得模糊。
範例 3️⃣ 背景透明 + CSS 控制
import * as THREE from 'three';
const renderer = new THREE.WebGLRenderer({ alpha: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 直接在 CSS 設定背景顏色
renderer.domElement.style.background = 'rgba(0,0,0,0)'; // 完全透明
// 若想要半透明
// renderer.domElement.style.background = 'rgba(255,255,255,0.5)';
應用:在製作 HUD(Head‑Up Display) 或與其他 HTML 元素混合時,透明背景非常有用。
範例 4️⃣ 啟用陰影與陰影貼圖
import * as THREE from 'three';
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.shadowMap.enabled = true; // ★ 啟用陰影
renderer.shadowMap.type = THREE.PCFSoftShadowMap; // 柔化陰影(效能稍低)
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
提示:陰影渲染會顯著增加 GPU 負擔,僅在需要真實感的場景中使用,且要配合光源 (
DirectionalLight、SpotLight) 與可投射陰影的物件 (mesh.castShadow = true)。
範例 5️⃣ 色彩編碼與色調映射(提升真實感)
import * as THREE from 'three';
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 讓顏色更貼近相機感光特性
renderer.outputEncoding = THREE.sRGBEncoding;
// 使用 ACES Filmic 風格的色調映射
renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.toneMappingExposure = 1.0; // 曝光值,可自行調整
// 後續:載入 HDR 環境貼圖會更有感
說明:若場景使用 HDR 環境貼圖、PBR 材質(MeshStandardMaterial、MeshPhysicalMaterial),建議一定要設定
outputEncoding為sRGBEncoding,並依需求開啟色調映射,才能避免顏色過暗或過亮。
常見陷阱與最佳實踐
| 常見問題 | 為什麼會發生 | 解決方案 / 最佳實踐 |
|---|---|---|
| 畫面渲染模糊 | 未設定 setPixelRatio 或 antialias 關閉 |
在高 DPI 裝置上必須 renderer.setPixelRatio(window.devicePixelRatio);同時開啟 antialias(若硬體支援) |
| 背景顏色不透明 | alpha 預設 false,導致 canvas 背景被覆寫 |
建立渲染器時加入 { alpha: true },並在 CSS 中自行設定 background |
| 陰影不顯示 | 陰影相關屬性未全部開啟或光源類型不支援 | renderer.shadowMap.enabled = true、光源 castShadow = true、物件 castShadow / receiveShadow = true,且光源必須是 DirectionalLight、SpotLight 或 PointLight |
| 顏色失真(過暗或過亮) | 沒有設定正確的色彩編碼或色調映射 | renderer.outputEncoding = THREE.sRGBEncoding;若使用 HDR,開啟 toneMapping(例如 ACESFilmicToneMapping) |
| 視窗大小變動後畫面比例錯亂 | 未監聽 resize 事件並更新渲染器尺寸與相機比例 |
javascript window.addEventListener('resize', ()=>{ const w = window.innerWidth; const h = window.innerHeight; renderer.setSize(w,h); camera.aspect = w/h; camera.updateProjectionMatrix(); }); |
最佳實踐小結
- 一律使用
setPixelRatio,確保跨裝置畫質一致。 - 開發階段先開啟抗鋸齿,上線前根據效能需求再決定是否關閉。
- 若需要透明背景,務必在建立渲染器時加入
alpha:true,並自行控制 CSS。 - 陰影、HDR、色調映射等高階特效,僅在需求明確且硬體允許時使用,避免一開始就把效能拉低。
- 永遠在
resize事件裡同步更新渲染器與相機,保證使用者調整視窗大小時畫面不會變形。
實際應用場景
| 場景 | 為何需要特定渲染器設定 | 範例說明 |
|---|---|---|
| 產品 3D 展示(電商) | 需要透明背景讓產品與頁面 UI 無縫結合,且要保持高解析度 | 使用 alpha:true + setPixelRatio,關閉陰影以提升效能 |
| 互動式資料視覺化 | 大量點雲或線條,抗鋸齒能提升可讀性 | antialias:true,同時使用 WebGL2Renderer(Three.js 自動選擇) |
| 遊戲或沉浸式體驗 | 需要真實光照、陰影與 HDR 環境 | shadowMap.enabled、outputEncoding = sRGBEncoding、toneMapping = ACESFilmicToneMap |
| AR/VR WebXR | 需要高幀率與正確的色彩空間,且畫布尺寸會隨裝置變化 | setPixelRatio、outputEncoding、在每個 frame 前呼叫 renderer.setSize 以匹配 XRSession 解析度 |
| 教育平台(教學動畫) | 常在不同裝置(平板、手機)展示,需保證畫面不失真 | setPixelRatio + resize 監聽,保持比例正確 |
總結
THREE.WebGLRenderer 是 Three.js 生態系的核心入口,正確的建立與設定直接決定了 效能、畫質與開發彈性。本文從 為什麼選擇 WebGLRenderer、基本建立流程、關鍵屬性與方法,再到 五個實作範例、常見陷阱與最佳實踐,最後列出 真實應用情境,提供了完整的知識地圖。
掌握渲染器的設定,就等於掌握了 3D 網頁開發的基礎底層。未來在加入光源、材質、後期特效時,只要回顧本文的要點,就能快速定位問題、調校效能,讓你的 Three.js 專案在各種裝置上都能保持流暢且美觀的表現。
祝開發順利,期待看到你用 Three.js 打造的精彩 3D 作品! 🚀