IBL 基于图像的光照:原理与实现
什么是 IBL
IBL(Image-Based Lighting,基于图像的光照)是一种使用环境贴图(通常是 HDRI)来照亮物体的技术。它将周围环境的光照信息编码到纹理中,通过采样该纹理为物体提供漫反射和镜面反射光照,使物体与场景环境自然融合。IBL 是 PBR 工作流中实现全局光照和反射的重要组成部分。
IBL 的原理
环境贴图记录了从各个方向入射的光照。对于表面上的一个点,其反射光包括:
- **漫反射部分**:来自所有方向的入射光经表面漫反射后的积分,通常较均匀。
- **镜面反射部分**:来自反射方向附近的光,取决于表面粗糙度。粗糙度越低,反射越锐利;粗糙度越高,反射越模糊。
直接采样环境贴图进行实时积分计算成本高昂,因此通常使用预计算技术。
预计算过程
IBL 的预计算通常包括以下步骤:
- **生成辐照度贴图(Irradiance Map)**:用于漫反射光照。对原始环境贴图进行卷积,计算每个方向的半球积分(即 Lambertian 漫反射)。结果是一个低频、模糊的贴图,可以直接采样用于漫反射。
- **生成预滤波环境贴图(Prefiltered Environment Map)**:用于镜面反射。对原始环境贴图进行不同粗糙度级别的高斯滤波,生成一系列 Mipmap 级别,每个级别对应一个粗糙度。粗糙度越高,滤波越强。在着色器中,根据表面粗糙度选择合适的 Mipmap 级别。
- **生成 BRDF 积分查找表(BRDF LUT)**:用于加速镜面反射计算。该 LUT 存储了菲涅尔项和几何项的积分,通常以 2D 纹理表示,横轴为 NdotV(法线与视线点积),纵轴为粗糙度。在着色器中,采样 LUT 并结合预滤波环境贴图得到镜面反射。
- 计算漫反射光照:`irradiance = textureCube(irradianceMap, N).rgb * albedo`
- 计算镜面反射:
- 将漫反射和镜面反射相加,得到环境光照。
这些预计算可以在引擎启动时或离线完成。Unity 和 Unreal 在导入 HDRI 时自动进行预计算。
在着色器中的实现
在片段着色器中,使用 IBL 的典型流程:
- 采样预滤波环境贴图:`prefilteredColor = textureCubeLod(prefilteredMap, R, roughness * maxMipLevel).rgb`
- 采样 BRDF LUT:`brdf = texture2D(brdfLUT, vec2(NdotV, roughness)).rg`
- 镜面反射 = `prefilteredColor * (F * brdf.x + brdf.y)`
IBL 与直接光照的结合
IBL 通常与直接光照(点光源、方向光等)结合使用。IBL 提供环境光照和反射,直接光照提供主要的阴影和高光。在 PBR 中,两者都使用相同的 BRDF,确保一致性。
常见问题
IBL 和直接光照有什么区别?
直接光照来自离散光源(如点光源、方向光),IBL 使用环境贴图模拟来自所有方向的间接光照。
为什么需要预计算?
实时计算环境光照的积分非常昂贵,预计算将复杂积分转化为纹理查找,大幅提升性能。
IBL 支持动态环境吗?
支持,但预计算需要在环境变化时重新进行,对于动态环境可以使用实时反射探针或简化方法。
移动端可以使用 IBL 吗?
可以,移动端通常使用较低分辨率的预计算贴图,并简化 BRDF LUT,以节省性能。
HDRI 和 IBL 有什么关系?
HDRI 是 IBL 的数据源,通常作为环境贴图。IBL 利用 HDRI 提供的光照信息进行渲染。
常见问题
IBL 和直接光照有什么区别?
直接光照来自离散光源,IBL 使用环境贴图模拟来自所有方向的间接光照。
为什么需要预计算?
实时计算环境光照积分非常昂贵,预计算将复杂积分转化为纹理查找,大幅提升性能。
IBL 支持动态环境吗?
支持,但预计算需在环境变化时重新进行,动态环境可用实时反射探针或简化方法。
移动端可以使用 IBL 吗?
可以,移动端通常使用较低分辨率预计算贴图,并简化 BRDF LUT 以节省性能。
HDRI 和 IBL 有什么关系?
HDRI 是 IBL 的数据源,通常作为环境贴图。IBL 利用 HDRI 提供的光照信息进行渲染。