ARCore 中文文档 下载 App

光照估算让虚拟物体融入真实光线

为什么虚拟物体看起来"假"

在没有光照估算的 AR 应用里,虚拟物体通常使用一个固定的光色(比如白色)和固定的光照强度。白天在阳光下、夜晚在白炽灯下、阴天在散射光下——同一个虚拟物体在所有环境里看起来都一样。结果就是:虚拟物体的光影和真实环境对不上,用户一眼就能看出"这是假的"。

光照估算(Light Estimation)的目标就是:让 ARCore 自动分析当前画面中的光照条件,然后把这些信息提供给你的 3D 渲染引擎,让虚拟物体呈现出与周围环境一致的明暗和色温。

两种光照估算模式

ARCore 提供两种精度的光照估算:

模式一:基础光照估算(默认)

输出两个标量值:

输出含义用途
AverageIntensity当前环境的平均光强(0 ~ 1 之间)直接作为 3D 引擎的 ambient light 强度
ColorCorrection色温校正向量(r, g, b 三个系数)调整虚拟物体的颜色,匹配环境色温

基础模式开销小、覆盖所有 ARCore 设备。

模式二:HDR 光照估算

输出一个 HDR 环境贴图(Cube Map)——这是从摄像头画面提取的球面全景光信息,相当于把当前环境的所有光线方向和强度编码进一个 6 面立方体贴图里。

HDR 模式可以实现:

但 HDR 模式需要更多计算资源和内存,对低端设备可能有压力。

Session 配置

session.configure(
    Session.Config(context).apply {
        // 基础模式默认开启,显式设置也可以
        setLightEstimationMode(
            Session.Config.LightEstimationMode.AMBIENT_INTENSITY
        )

        // 或 HDR 模式(如果设备支持)
        if (session.isHdrLightEstimationSupported()) {
            setLightEstimationMode(
                Session.Config.LightEstimationMode.ENVIRONMENTAL_HDR
            )
        }
    }
)

读取光照数据

基础光照

session.update(frame)

// LightEstimate 对象在 Frame 上
val estimate = frame.lightEstimate

// 只有 ESTIMATE_VALID 状态的才可用
if (estimate.state != LightEstimate.State.VALID) return

// 平均光强(0 ~ 1)
val intensity = estimate.averageIntensity

// 色温校正(ColorCorrection)
// 是一个 Vector3:(r, g, b) 三个分量的校正系数
// 把 3D 引擎的 ambient light color 乘以这个向量即可
val colorCorrection = estimate.colorCorrection

// 应用到渲染引擎(伪代码)
renderEngine.ambientLight.intensity = intensity
renderEngine.ambientLight.color = ambientBaseColor * colorCorrection

HDR 光照

val estimate = frame.lightEstimate
if (estimate.state != LightEstimate.State.VALID) return

// 环境贴图 Cube Map
val cubeMap = estimate.environmentHdrCubeMap
// cubeMap 是一个 OpenGL Cube Map 纹理 ID(Android)
// 可以直接传给 PBR 材质做环境反射

// 也可以获取 HDR 颜色校正(比基础模式更精确)
val hdrColorCorrection = estimate.colorCorrection

渲染集成要点

OpenGL ES 中的着色器修改

你的 3D 着色器需要能接收光照估算值:

// 片段着色器
uniform float uAmbientIntensity;     // ARCore AverageIntensity
uniform vec3 uColorCorrection;       // ARCore ColorCorrection

void main() {
    // 基础光照(每个像素一样强)
    vec3 ambient = baseColor * uAmbientIntensity * uColorCorrection;

    // 加上方向光等...
    vec3 finalColor = ambient + diffuse + specular;

    gl_FragColor = vec4(finalColor, 1.0);
}

HDR Cube Map 在 PBR 材质中的使用

如果你用的是基于物理的渲染(PBR),HDR Cube Map 可以直接作为 environmentMap 传入——PBR 着色器会自动用它计算反射、折射和环境遮蔽,效果最接近真实。

Unity AR Foundation 中的光照

Unity 把光照估算封装进 AR Session 和渲染管线。配置 Universal Render Pipeline(URP)或 HDRP 后:

// 自动应用光照估算
var lightEstimate = session.Subsystem.systemState;

// Unity 2021+ 的 AR Session Manager 自动处理光照更新
// 把 Light Estimation 数据注入到渲染管线中

Unity 会自动把 ARCore 的 AverageIntensity 映射到场景的 Global Light Intensity,ColorCorrection 映射到 Global Light Color。

光照估算的局限性

局限说明
全局估算平均光强是整个画面的平均值,局部强光/弱光不敏感
延迟HDR 模式的 Cube Map 更新频率可能低于摄像头帧率
动态光快速变化的光(如闪光灯、快速移动的手电筒)滞后
方向单一基础模式不包含光的方向信息(只知道亮暗和色温)

局部光 vs 全局光

一个折中的优化方案:根据虚拟物体在屏幕上的位置,只取该区域附近的光照值而不是整个画面的平均值。这样放在阴影里的物体会更暗、放在阳光下的物体更亮。

性能开销

模式CPU 开销GPU 开销内存适用设备
基础 AMBIENT_INTENSITY极低无可忽略所有 ARCore 设备
HDR ENVIRONMENTAL_HDR中中中(HDR Cube Map 纹理)中高端设备,低端手机可能自动降级

HDR 模式在 Android 上会自动降级——如果 GPU 能力不够,ARCore 会退回到基础光照模式,不会让应用崩溃。你只需要在 Session 配置里指定 ENVIRONMENTAL_HDR 即可。

light-estimation.jpg
光照估算效果:虚拟物体的色调和亮度匹配周围环境光