小林第一次给舞台剧《水晶森林》布光时,只在天花板挂了一排主灯。演员被照得雪亮,可身后的树影、角落的道具全部陷进一片死黑,像被黑洞吞掉一样。观众觉得画面“假”,却说不出哪里不对。老灯光师路过,笑着点破:“你只算了灯直接照过去的光,没算光在墙壁、地板、道具之间弹来弹去的光。”这句话,就是全局光照(Global Illumination, GI)最朴素的直觉。 真实世界里,光从灯出发后不会只打中一个物体就消失。它会弹到墙上、地面上,再弹到别的物体上,一次次把能量传递下去,最后才进入我们的眼睛。计算机渲染里,我们把“灯直接照到表面”的光叫直接光,把“别的表面反射过来”的光叫间接光。只算直接光,阴影会黑死,画面像布景;把两种光一起算清楚,画面才有了“空气感”和“真实感”。要做到这件事,主流招数有两套:路径追踪像派出一队“光线侦察兵”,从观众的眼睛出发,在场景里摸黑漫游,替每个像素寻找灯光;光子映射则像往舞台撒一把荧光粉,让光子从灯出发在物体表面弹跳、留下印记,再统计光子密度来推算亮度。而到了游戏这样的实时场景,演出一旦开始就不能停下来慢慢算,于是又有了烘焙GI和实时GI的取舍。 学完这篇文章,你会明白为什么有GI的画面“看着对劲”,也能在画质、性能之间做出聪明的选择。

岗位关联

掌握全局光照,你就能在渲染项目中正确选择GI方案,让画面真实的同时守住性能预算,成为团队里“懂光影”的图形学工程师。

目录
  1. 可视化演示
  2. 光照概述:总光量等于直射加反弹
  3. 直接光算法:灯泡和它的直射法则
  4. 间接光本质:光在舞台上的多次弹跳
  5. 路径追踪:让光线侦察兵去舞台寻光
  6. 光子映射:先撒光子再看印记
  7. 实时与烘焙:现场调光 vs 提前布光
  8. 方案选型:怎么挑合适的GI方案
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

交互展示光线弹射与间接照明、路径追踪算法过程和不同GI方案对比效果,理解真实光影的核心原理。

本节配有交互动效(进入视口后自动加载,约 3KB)。

光线弹射:直接光与间接光 光源直接照射表面产生直射光照 光线在物体间反弹产生间接照明 L = L_direct + L_indirect 间接光让阴影区域也有色彩

光照概述:总光量等于直射加反弹

小林刚接手《水晶森林》时,只在天花板挂了几盏主灯,把演员照得发亮,可身后的树影深不见底。老灯光师告诉他:“你把光想得太简单了。一盏灯照过来,光会撞到地上、墙上,再弹到演员身上。你要算的不只是刚才那一道直射,还有这些‘弹过来的光’。”这就是全局光照的直觉起点:真实世界的光,从来不是一次性买卖。

在计算机图形学里,我们把光源直接照射到物体表面的过程叫直接光,把光在表面之间多次反射后再照过来的过程叫间接光。一个渲染画面如果只有直接光,阴影区域会接近全黑,像是硬生生抠出来的剪影;加上间接光后,阴影里会有朦胧的环境反光,物体之间的颜色也会互相沾染,画面立刻“活”起来。全局光照(GI)指的就是把这两部分光都计算出来的渲染技术。

要理解GI到底在算什么,可以先把它拆成一个加法:

小林终于明白,自己之前只做了加法的前半部分。全局光照要把“反弹的光”也补进公式里,舞台才不会有黑洞洞的角落。

Ltotal=Ldirect+Lindirect\displaystyle L_{\text{total}} = L_{\text{direct}} + L_{\text{indirect}}
这个公式是说:你最终看到的表面亮度,等于光源直接照过来的部分,加上其他表面反弹过来的部分。
  1. 总出射亮度 \(L_{\text{total}}\)这是物体表面最后进入相机或眼睛的光量,也就是像素最终要显示的颜色值。
    LtotalL_{\text{total}}
  2. 直接光项 \(L_{\text{direct}}\)光源发出的光线直接打到当前表面,再反射进眼睛的成分。它决定了物体亮面和高光的位置。
    LdirectL_{\text{direct}}
  3. 间接光项 \(L_{\text{indirect}}\)场景中其他表面先接住光,再反射到当前表面的成分。它照亮了阴影区域,也带来颜色溢出。
    LindirectL_{\text{indirect}}

直接光算法:灯泡和它的直射法则

小林开始给演员打主光时,老灯光师提醒他:“你光把灯打开还不够,灯离演员多远、从哪个方向照、中间有没有被布景挡住,都会改变脸上亮不亮。”这些正是直接光计算要回答的问题。

在渲染里,光源常被抽象成点光源、平行光和聚光灯。点光源的光强会随着距离平方衰减,离得越远越暗;平行光则像太阳一样没有衰减,只保留方向。而一个表面到底能接住多少光,关键看表面法线方向和光线方向的夹角——这就是朗伯余弦定律。

对于常见的漫反射表面,直接光贡献可以写成:

小林调整灯的远近和角度时,其实就是在调这两个因子。直接光把演员的轮廓打亮了,可新的问题又来了:影子边缘依然太硬、太黑,就像舞台被切成了两半。

Ld=kd⋅Ir2⋅max⁡(0,n⋅l)\displaystyle L_d = k_d \cdot \frac{I}{r^2} \cdot \max(0, \mathbf{n}\cdot\mathbf{l})
它告诉我们:漫反射表面接收到的光,由材质颜色、距离衰减和光照角度共同决定。
  1. 漫反射系数 \(k_d\)表示表面材质本身的颜色,比如红色苹果的 \(k_d\) 偏向红通道,它决定了反射光的颜色。
    kdk_d
  2. 距离衰减项 \(I / r^2\)点光源的能量均匀扩散到球面上,距离 \(r\) 越远,单位面积收到的能量越少,所以除以半径的平方。
    Ir2\frac{I}{r^2}
  3. 朗伯余弦项 \(\max(0, \mathbf{n}\cdot\mathbf{l})\)表面法线 \(\mathbf{n}\) 与光线方向 \(\mathbf{l}\) 的点积等于两者夹角的余弦;夹角超过 90 度说明光从背面照来,取 0 表示照不到。
    max⁡(0,n⋅l)\max(0, \mathbf{n}\cdot\mathbf{l})

间接光本质:光在舞台上的多次弹跳

小林蹲在舞台边观察,发现演员脚下的影子虽然深,却隐隐约约能看到地毯的纹路;侧幕的蓝布也把一圈淡淡的蓝色光晕染到了白色道具上。老灯光师说:“这就是反弹的光。你以为光只走一条直线,其实它像接力赛一样,被一个表面接住,再传给下一个表面。”

要精确描述这种“接力”,图形学引入了渲染方程。它把自发光、材质反射、入射光方向和夹角余弦全部整合在一起。虽然名字吓人,本质却只是一本“光线接力规则手册”。

这个方程像一个总纲,路径追踪和光子映射其实都是在想方设法求解它。不同的是,它们计算“接力”的方式完全不同。

Lo(ωo)=Le(ωo)+∫Ωfr(ωi,ωo)Li(ωi)(n⋅ωi) dωi\displaystyle L_o(\omega_o) = L_e(\omega_o) + \int_{\Omega} f_r(\omega_i, \omega_o) L_i(\omega_i)(\mathbf{n}\cdot\omega_i)\, d\omega_i
渲染方程告诉我们:一个点自己发出的光,加上从四面八方入射的光经过材质反射后射向相机的光,就是它最终显示的颜色。
  1. 自发光项 \(L_e(\omega_o)\)如果表面本身是光源(比如灯管),它不需要别处的光就能发光;普通物体这一项为 0。
    Le(ωo)L_e(\omega_o)
  2. BRDF 材质函数 \(f_r(\omega_i, \omega_o)\)描述一个表面如何把某个方向来的光反射到另一个方向,是决定材质质感的核心。
    fr(ωi,ωo)f_r(\omega_i, \omega_o)
  3. 半球积分 \(\int_{\Omega} \cdots d\omega_i\)光可以从表面上半球的任意方向打过来,所以要把所有方向上的贡献累加起来。
    ∫Ω⋯dωi\int_{\Omega} \cdots d\omega_i
  4. 夹角余弦 \((\mathbf{n}\cdot\omega_i)\)入射方向越斜,表面能接住的能量越少,这和直接光中的朗伯余弦是同一个道理。
    (n⋅ωi)(\mathbf{n}\cdot\omega_i)

路径追踪:让光线侦察兵去舞台寻光

小林不想只靠经验猜,他问老灯光师有没有更“笨”但更准的办法。老灯光师指了指观众席:“你派几个侦察兵,从观众眼睛出发,在舞台里漫游。他们遇到演员就按材质弹一下,遇到墙就再弹一下,最后谁找到了灯源,就回来报告亮度。派的人越多,报告越可靠。”小林听完,立刻想到了路径追踪。

路径追踪是离线渲染中最常用的GI算法。对每个像素,我们发射若干条光线,让它们在场景中随机反弹,直到命中光源或被随机终止;然后把所有光线的贡献平均,作为该像素的亮度。这个过程在数学上就是蒙特卡洛积分。

侦察兵越多,画面越干净;可每个像素都要几百上千条路径,电影渲染一帧常常要烧几小时。这让小林意识到,追求真实是有代价的。

⟨Lo⟩=1N∑k=1Nfr(ωk,ωo)Li(ωk)(n⋅ωk)p(ωk)\displaystyle \langle L_o \rangle = \frac{1}{N}\sum_{k=1}^{N} \frac{f_r(\omega_k, \omega_o)L_i(\omega_k)(\mathbf{n}\cdot\omega_k)}{p(\omega_k)}
这个公式用 \(N\) 条随机光线来估计渲染方程中的积分,每条光线的贡献都要除以它被采样到的概率,才能保证结果无偏。
  1. 样本数量 \(N\)每个像素发射的路径数。显然,\(N\) 越大,结果越接近真实积分,但渲染时间也线性增长。
    NN
  2. 随机采样方向 \(\omega_k\)每条路径在表面反弹时,会随机选择一个方向继续前进,这正是“侦察兵”的漫游路线。
    ωk\omega_k
  3. 概率密度 \(p(\omega_k)\)我们越容易采到某个方向,单个样本代表的面就越小,所以要把贡献除以 \(p\) 来抵消这种不均匀。
    p(ωk)p(\omega_k)
  4. 平均符号 \(\langle \cdot \rangle\)尖括号表示这是一个统计估计值,不是精确积分值,样本越多,它越收敛。
    ⟨Lo⟩\langle L_o \rangle

光子映射:先撒光子再看印记

有一次排练,老灯光师没有派侦察兵,而是搬来一袋“荧光粉”往舞台上一撒。荧光粉变成许多细小的光子,从灯里飞出来,在演员和布景上撞来撞去,留下发光印记。小林蹲在地上数那些印记的密度,惊讶地发现:哪个地方光子落得多,哪个地方就亮。这就是光子映射的思路。

光子映射分为两步。第一步叫光子发射:从光源发射大量光子,让它们在场景中弹跳,每次撞到表面就把自己的位置和能量记录进一张“光子图”。第二步叫光子收集:渲染某个表面点时,在它周围找一个半径 \(r\),统计圆内所有光子的能量,再除以面积得到亮度。

荧光粉撒得密,亮度分布就平滑;撒得稀,就会出现一块亮一块暗的“光子噪声”。而且这种估计用的是密度近似,所以路径追踪无偏,光子映射却带有轻微偏差。

Lr(x,ω)≈1πr2∑p=1Mfr(x,ωp,ω)Φp\displaystyle L_r(x,\omega) \approx \frac{1}{\pi r^2}\sum_{p=1}^{M} f_r(x,\omega_p,\omega)\Phi_p
光子映射用“近邻光子能量和除以搜索圆面积”来估计某一点接到的间接光,落子越密,估计越稳。
  1. 搜索半径 \(r\)以当前表面点为圆心,统计多大范围内的光子会影响它。半径太小会漏光,太大画面会糊。
    πr2\pi r^2
  2. 光子能量 \(\Phi_p\)每个光子从光源出发时携带一份能量,每反弹一次都会损失,越晚到达的光子能量越弱。
    Φp\Phi_p
  3. 光子数量 \(M\)统计圆内实际收集到的光子数。光子越多,密度估计噪声越小。
    MM
  4. 材质反射 \(f_r(x,\omega_p,\omega)\)不同材质对光子的反弹方式不同,光泽表面会把能量集中反射,粗糙表面会均匀散开。
    fr(x,ωp,ω)f_r(x,\omega_p,\omega)

实时与烘焙:现场调光 vs 提前布光

演出正式开始后,舞台灯光不能再一遍遍彩排。小林发现,固定布景上的光效可以提前画好,但演员会走来走去,光在他们身上得实时变化。老灯光师给出了两套方案:烘焙GI和实时GI。

烘焙GI(光照贴图)是在离线阶段,先把静态场景的光照结果预计算出来,存进纹理。运行时只需查一下纹理,几乎不花额外性能。但场景里的物体位置、光源颜色一旦改变,贴图就失效了。实时GI则用光照探针、屏幕空间全局光照等手段,在每一帧快速近似计算间接光,专门服务动态物体和动态光源。

光照贴图的预计算,本质上是把每个表面点的反射光提前求出来:

固定布景用烘焙贴图,动态演员用实时探针,两者配合,演出才又真实又流畅。小林终于明白,真实和性能不是单选题,而是搭配题。

B(x)=∫Ωfr(x,ωi)Lin(x,ωi)(n⋅ωi) dωi\displaystyle B(x) = \int_{\Omega} f_r(x,\omega_i)L_{\text{in}}(x,\omega_i)(\mathbf{n}\cdot\omega_i)\, d\omega_i
烘焙阶段把渲染方程中的积分结果算好并存在纹理里,运行时只需要“查表”,而不是重新积分。
  1. 烘焙值 \(B(x)\)表示表面点 \(x\) 最终被记录到光照贴图中的亮度,离线算完后运行时直接读取。
    B(x)B(x)
  2. 入射辐射 \(L_{\text{in}}(x,\omega_i)\)包括直接光和各种反弹光,烘焙时已经把它们全部打进这个函数里。
    Lin(x,ωi)L_{\text{in}}(x,\omega_i)
  3. 积分域 \(\Omega\)对所有可能照到 \(x\) 点的方向求和,这正是GI要计算的核心,也是性能主要消耗点。
    Ω\Omega
  4. 预计算的含义括号里整个积分在离线完成,运行时只剩一个纹理采样操作,所以烘焙GI很快。
    ∫Ω⋯dωi\int_{\Omega} \cdots d\omega_i

方案选型:怎么挑合适的GI方案

《水晶森林》巡演到不同剧场,预算和排练时间都不一样。小剧场只能走一次台,来不及精雕细琢;大剧院则有充足时间反复调光。对应到渲染领域,工程师也得根据场景规模、动态元素、硬件预算来选GI方案,而不是无脑上最贵的算法。

选型时最常看的是性能预算:每帧渲染时间就那么点,GI吃掉太多,游戏就会卡成幻灯片。我们可以把GI的开销写成一个粗略公式:

想要舞台又亮又好还便宜,往往得混搭:关键角色用实时GI,远处布景用烘焙GI,偶尔再来一次离线预计算。这正是现代游戏引擎最流行的做法。

TGI=Nrays×Nbounces×Cray+Toverhead\displaystyle T_{\text{GI}} = N_{\text{rays}} \times N_{\text{bounces}} \times C_{\text{ray}} + T_{\text{overhead}}
总GI开销约等于“光线数量 × 反弹次数 × 单条光线求交成本”再加上固定开销,任何一项失控都会让性能雪崩。
  1. 每像素光线数 \(N_{\text{rays}}\)路径追踪中每个像素发射多少条路径;光线越多,噪声越低,但开销线性上升。
    NraysN_{\text{rays}}
  2. 最大反弹次数 \(N_{\text{bounces}}\)光最多在场景中弹几次。反弹次数越多,间接光越全,但每多一次都意味着新一轮求交。
    NbouncesN_{\text{bounces}}
  3. 单条光线求交成本 \(C_{\text{ray}}\)每条光线要判断是否撞到物体、撞到哪个物体,场景越复杂,这个成本越高。
    CrayC_{\text{ray}}
  4. 固定开销 \(T_{\text{overhead}}\)例如纹理上传、降噪、数据组织等与GI算法无关但必须花的钱。
    ToverheadT_{\text{overhead}}

AI 应用场景

电影与影视特效的离线渲染

阶段:渲染农场中的光照结算

解决的问题:传统打光需要美术逐帧手动补光,遇到复杂反射和透射时耗时巨大且不真实;路径追踪GI让光自己“弹”,大幅减少人工干预,同时获得可信的全局光影。

具体案例:在制作动画电影《森林奇遇》时,主角穿行在斑驳的树影中。团队用路径追踪渲染,每像素采样512条光线,最多反弹6次,树叶间的颜色溢出和柔和的阴影都能自动计算出来。最终画面里,角色的衣服会“染”上树叶的绿光。

游戏引擎的实时全局光照

阶段:实时渲染管线的光照集成

解决的问题:游戏画面必须达到60帧以上,路径追踪太慢无法直接使用;通过烘焙光照贴图叠加光照探针,或使用屏幕空间GI等近似算法,让动态角色在静态场景中也能获得实时间接光。

具体案例:在开放世界游戏《流光之城》中,建筑和地面使用烘焙GI存储日间光照,玩家角色使用球形光照探针实时取样;当太阳角度变化时,引擎只更新探针数据,既保真又保帧率。

建筑与室内可视化的混合GI方案

阶段:交互漫游的实时预览

解决的问题:建筑师想在不同时间、不同天气下查看室内光效,离线渲染太慢,纯实时全程GI又扛不住。于是静态家具和墙面用烘焙GI,可移动模型和灯具开关用实时GI,实现流畅又逼真的漫游体验。

具体案例:某室内设计平台让用户拖动沙发时,沙发阴影能跟随太阳光实时转动,而地板和墙面的漫反射光依然来自烘焙贴图。用户在浏览器里就能看到接近真实照片的光影效果。

Python 演示

python31 行
import mathimport random  def true_irradiance(amplitude=1.0):    """理论值:环境光 A*cos(theta) 在半球上积分的解析结果"""    return 2.0 * math.pi * amplitude / 3.0  def estimate_irradiance(samples):    """用均匀半球采样估计半球积分:E = ∫ Li * cos(theta) dω"""    total = 0.0    for _ in range(samples):        z = random.random()                # 采样 cos(theta),均匀分布在 [0,1]        phi = random.uniform(0.0, 2.0 * math.pi)        cos_theta = z        # 简化场景:入射辐射 Li 与 cos(theta) 成正比(头顶最亮)        Li = cos_theta        # 蒙特卡洛估计:贡献 = Li * cos_theta / pdf,pdf = 1/(2*pi)        total += Li * cos_theta * (2.0 * math.pi)    return total / samples  if __name__ == "__main__":    random.seed(42)    target = true_irradiance()    print("样本数     估计值     理论值     误差")    for samples in [100, 1000, 10000, 100000]:        est = estimate_irradiance(samples)        err = abs(est - target)        print(f"{samples:6d} {est:10.4f} {target:10.4f} {err:10.4f}")
目的:演示路径追踪核心的蒙特卡洛积分——用随机方向采样估计一个表面点的间接光照,并观察样本数增加时估计值逐渐收敛。
  1. random.random()均匀采样半球方向中 \(\cos\theta\) 的取值,路径追踪里这就是对入射方向的“侦察采样”。
  2. total += Li * cos_theta * (2.0 * math.pi)把当前样本的贡献累加,除以 pdf \(1/(2\pi)\) 后相当于乘以 \(2\pi\)。
  3. return total / samples对所有样本取平均,得到 \(\langle L_o\rangle\) 的估计值,样本越多越接近真实积分。
  4. true_irradiance()用解析积分算出理论值,用来和蒙特卡洛估计对比,帮助理解“收敛”的含义。

常见误区

误区我见过很多渲染软件里有“全局光照”复选框,是不是勾上它,灯光就自动完美了?我只需要点一下就行。

正解GI不是一个万能开关,而是一类算法的集合。路径追踪、光子映射、烘焙GI各有各的适用场景和参数,比如采样数、反弹次数、搜索半径。就像灯光师不能靠一个“自动布光”按钮搞定所有舞台,他必须根据剧本选择主光、补光还是环境光。

为何常见:因为许多现成引擎把GI封装成了简单的开关,降低了使用门槛,但也让初学者误以为背后没有取舍。

误区我用了路径追踪,画面还是好多颗粒噪点,是不是我的代码写错了?理论上路径追踪不应该完美吗?

正解路径追踪是基于蒙特卡洛积分的统计估计,样本数量不够时必然出现噪声。减少噪声通常是增加每像素采样数,或者使用降噪算法,而不是修改一个魔法参数。就像侦察兵人数太少,给回的情报自然东拼西凑。

为何常见:教程经常展示高样本下的最终渲染图,忽略了渲染耗时和噪声收敛过程,让初学者以为路径追踪开箱即得干净画面。

误区听说路径追踪和光子映射都是算GI的,那我随便用一个就行吧?反正都是往场景里射光线。

正解两者思路完全不同。路径追踪从相机出发,向场景随机反弹并寻找光源,是一种无偏估计;光子映射从光源出发,先把光子撒进场景,再在渲染时统计表面附近的光子密度,有偏但前期预处理后收集效率高。一个像派侦察兵找灯,一个像撒荧光粉看印记。

为何常见:两个算法都会和“光子”“射线”打交道,表面名词相似,容易在概念上被混淆。

误区我先把场景光照烘焙成贴图,然后把灯光颜色实时改了,为什么场景没有跟着变?是不是烘焙坏了?

正解烘焙GI是把固定的光照结果预计算进纹理,它天然只能配合静态场景和固定光源。一旦物体移动或光源改变,贴图里的信息就失效了。动态元素需要光照探针、屏幕空间GI等实时技术来补充,而不是依赖烘焙贴图。

为何常见:光照贴图看起来是“一张图”,初学者很容易忽略它背后的预计算和静态假设。

误区实时GI做得再快也只是近似,画面肯定比电影差远了,何必费劲去调?

正解现代引擎通过烘焙、探针、屏幕空间GI、距离场等多种技术混合,已经能在保持帧率的同时输出非常自然的全局光照。实时GI不是要取代离线渲染,而是在性能预算内最大化真实感。就像现场调光虽然比不上大制作逐帧打磨,但依然能让观众沉浸其中。

为何常见:人们容易拿游戏帧率和电影的单帧渲染时间对比,忽略了工程上的巧妙妥协与组合创新。

面试题

Q1. 全局光照(GI)主要模拟光线的哪类现象?

单选题 · easy

  • A.只模拟光源直射表面的效果
  • B.模拟光线在物体间的反复弹射← 正确答案
  • C.只模拟相机镜头的畸变问题
  • D.只模拟物体纹理贴图的颜色

答案:B。GI的核心是同时计算直接光和间接光,其中间接光来自光线在物体间的反复弹射。选项B准确描述了这一现象;A只描述了直接光,C和D与光照无关。就像舞台剧里主灯打亮演员,而墙壁反弹的光照亮影子,缺了反弹就少了灵魂。

Q2. 在朗伯漫反射中,表面接收的光强与哪个量成正比?

单选题 · easy

  • A.法线与光照方向夹角的余弦← 正确答案
  • B.法线与视线方向夹角的正弦
  • C.光源到表面距离的三次方
  • D.光源颜色的透明度

答案:A。朗伯余弦定律指出,表面接收到的光强与法线 \(\mathbf{n}\) 和光照方向 \(\mathbf{l}\) 夹角的余弦成正比,即 \(\max(0,\mathbf{n}\cdot\mathbf{l})\)。灯光斜着照过来时,单位面积接住的光更少,所以没有余弦项的场景会显得不够自然。

Q3. 路径追踪获得清晰无噪画面通常需要?

单选题 · easy

  • A.减少每像素采样数尽快渲染
  • B.增加每像素采样光线数量← 正确答案
  • C.关闭场景中的间接光
  • D.只保留直接光不计算反弹

答案:B。路径追踪是蒙特卡洛积分,噪声来自样本不足。增加每像素采样光线数量可以让估计值更快收敛,画面更干净。减少采样、关闭间接光会加剧噪声或丢失GI效果,就像侦察兵太少时情报必然残缺。

Q4. 渲染方程中的 \(f_r\) 表示?

单选题 · mid

  • A.入射光线自身的频率大小
  • B.材质表面的光线反射分布函数← 正确答案
  • C.光线在场景中的传播速度
  • D.光源随距离增加的衰减系数

答案:B。\(f_r\) 是双向反射分布函数(BRDF),描述材质如何把某个入射方向的光反射到出射方向。它决定了表面是镜面、粗糙还是哑光。理解 \(f_r\) 是读懂渲染方程的关键,就像理解材质是解读“光线接力规则”的前提。

Q5. 光子映射的第一步是?

单选题 · mid

  • A.从相机随机发射光子到场景
  • B.从光源发射光子并跟踪其弹跳← 正确答案
  • C.从每个物体表面向四周散射光子
  • D.从光源位置删除所有无用光子

答案:B。光子映射的第一步是光子发射:从光源出发发射大量光子,让它们在场景中弹跳,并把每次撞击点记录到光子图中。第二步才是渲染时收集光子。这是“先撒荧光粉、再看印记”的两阶段流程。

Q6. 光照贴图属于哪种GI方案?

单选题 · mid

  • A.实时动态全局光照技术
  • B.离线预计算的烘焙光照方案← 正确答案
  • C.完全依赖物理的光线追踪方法
  • D.不需要预计算的屏幕空间技术

答案:B。光照贴图把GI结果提前烘焙到纹理中,运行时通过纹理采样快速取得光照值,因此属于离线预计算的烘焙GI方案。它适合静态场景和固定光源,速度很快,但无法自然响应动态物体。

Q7. 路径追踪的蒙特卡洛估计中,为什么要除以采样概率密度 \(p(\omega)\)?

单选题 · hard

  • A.为了提升画面整体亮度
  • B.为了消除采样方向不均匀带来的偏差← 正确答案
  • C.为了加快光线传播速度
  • D.为了让所有像素颜色一致

答案:B。蒙特卡洛积分要求对样本贡献除以该样本被采到的概率密度,这样才能保证即使某些方向更容易被采到,也不会被过高估计。没有这一项,结果会有系统性偏差。好比侦察兵容易走大路,但路上看到灯光不能代表所有角落。

Q8. 下列哪些属于常见GI算法?

多选题 · mid

  • A.路径追踪算法← 正确答案
  • B.光子映射算法← 正确答案
  • C.光栅化算法
  • D.烘焙光照贴图← 正确答案

答案:ABD。路径追踪、光子映射、烘焙光照贴图都是计算或近似全局光照的技术。光栅化只是把三角形投影到屏幕的绘制方法,本身不负责计算光线反弹,因此不属于GI算法。

Q9. 关于烘焙GI,下列说法正确的有?

多选题 · hard

  • A.适合静态场景与固定不变光源← 正确答案
  • B.运行时开销较小且速度较快← 正确答案
  • C.能自然支持动态物体位置移动
  • D.需要离线完成预计算过程← 正确答案

答案:ABD。烘焙GI把光照结果预计算到纹理中,运行时开销小、速度快,但只适用于静态场景和固定光源;物体移动时贴图不会更新。它不可能“自然支持”动态物体,这正是它需要光照探针等实时技术配合的原因。

Q10. 以下哪些技术可以用于实时GI的近似?

多选题 · extreme

  • A.使用光照探针做动态物体取样← 正确答案
  • B.使用屏幕空间全局光照近似← 正确答案
  • C.使用预计算光照贴图节省开销← 正确答案
  • D.每帧执行上百万条路径追踪

答案:ABC。光照探针、屏幕空间GI、预计算光照贴图都属于在性能可控范围内近似GI的常用手段。而每帧执行上百万条路径追踪是离线电影级渲染的做法,通常远超实时帧预算,因此不是实时GI的合适方案。