在基于物理的渲染(PBR)中,環境光貼圖是實現真實光照效果的核心組件之一。而將 HDR 全景圖轉換為立方體貼圖,是制作預過濾環境光貼圖的基礎步驟。本教程將詳細講解如何實現這一轉換過程。
什么是 HDR 轉立方體貼圖?
HDR(高動態范圍)全景圖通常以等矩形投影(Equirectangular Projection)的形式存在,看起來像一張橫向拉伸的長方形圖片。而立方體貼圖則由 6 個正方形面組成,分別對應空間中的 ±X、±Y、±Z 六個方向,更適合實時渲染中計算光線反射。
轉換的核心是將等矩形投影上的每個像素,正確映射到立方體貼圖的 6 個面上,同時保持 HDR 數據的完整性。
準備工作
在開始前,請確保你已具備:
- 基本的 Three.js 知識
- 一張 HDR 全景圖(.hdr 或.exr 格式)
- 配置好的 Three.js 環境(包含渲染器、場景、相機)
實現步驟
步驟 1:創建立方體貼圖渲染目標
首先,我們需要創建一個立方體貼圖渲染目標(WebGLCubeRenderTarget
),用于存儲轉換后的立方體貼圖數據:
const cubeTarget = new THREE.WebGLCubeRenderTarget(size, {format: THREE.RGBAFormat, // 使用RGBA格式type: THREE.HalfFloatType, // 半浮點數類型,平衡精度和性能generateMipmaps: true, // 生成多級漸遠紋理minFilter: THREE.LinearMipmapLinearFilter, // 縮小過濾方式magFilter: THREE.LinearFilter, // 放大過濾方式wrapS: THREE.ClampToEdgeWrapping, // S軸紋理包裹方式wrapT: THREE.ClampToEdgeWrapping, // T軸紋理包裹方式flipY: false // 不翻轉Y軸
});
參數說明:
size
:立方體貼圖每個面的尺寸(如 256、512)HalfFloatType
:保留 HDR 的高動態范圍信息,避免精度損失- 過濾方式選擇線性過濾,確保采樣平滑
步驟 2:編寫頂點著色器
頂點著色器的主要作用是傳遞 UV 坐標,并進行適當調整:
varying vec2 vUv0;
uniform vec4 uvMod;
void main() {gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);// 計算UV坐標,支持縮放和偏移vUv0 = (position.xy * 0.5 + 0.5) * uvMod.xy + uvMod.zw;
}
vUv0
: varying 變量,用于向片段著色器傳遞 UV 坐標uvMod
:用于調整 UV 的縮放和偏移,增加靈活性
步驟 3:編寫片段著色器(核心邏輯)
片段著色