渲染中光和材质
引言:绘制核心三要素与图形学发展史
这部分内容是整个渲染主题的开篇,旨在建立一个宏观的认知框架。讲座将渲染的核心拆解为三个基本要素,并将其发展历程比作一个充满智慧与妥协的探索故事。
-
核心观点: 现代游戏渲染的本质,是在极其有限的时间内,模拟光线、材质以及它们之间复杂的交互(通过着色器实现)。这个过程充满了大胆的假设、巧妙的简化和工程上的"Hack",是几十年来图形学领域顶尖智慧的结晶。
-
关键要素:
- 光照 (Lighting): 光的本质是光子,它从光源发出,经过一系列反射、吸收、折射后进入我们的眼睛。这是场景可见的根本原因。
- 材质 (Material): 描述了物体表面如何与光发生作用。是吸收、反射还是透射?是光滑如镜还是粗糙如石?材质决定了物体的外观。
- 着色器 (Shader): 实现上述光照与材质交互的具体计算程序。它是连接理论与最终像素颜色的桥梁。
渲染的基石:渲染方程 (The Rendering Equation)
为了从物理上精确描述光与物质的交互,我们需要一个统一的数学模型。这便是现代基于物理渲染(PBR)的理论基石——渲染方程。
-
核心观点: 35年前,图形学先驱 James Kajiya 提出了一个优雅的积分方程,它从物理层面统一描述了某个表面点在特定方向上的最终光照表现。这个方程是所有现代渲染算法的理论出发点。
-
关键人物: James Kajiya
-
渲染方程:
-
方程解析: 这个看似复杂的方程,可以拆解为几个关键部分来理解:
- : 出射光辉 (Outgoing Radiance)。这是我们最终要求解的目标:从表面点 沿 方向射出的光的能量。也就是我们人眼或摄像机最终看到的光。
- : 自发光项 (Emissive Term)。描述了点 自身作为光源发出的光。对于大部分不发光的物体,此项为零。
- : 积分项 (Integral Term)。代表了来自点 上方整个半球()所有可能方向的光线对最终出射光辉的总贡献。这是渲染方程最难计算的部分。
- : 入射光辉 (Incoming Radiance)。从 方向到达点 的光的能量。
- : 余弦项 (Lambert's Cosine Law)。 是表面法线。这个点积项描述了入射光能量的接收效率。 核心思想是:光线越是垂直照射到表面,单位面积接收的能量就越多。一个经典的例子是,地球上同样是太阳光,赤道地区(接近垂直照射)比两极地区(掠射)要热得多。
- : 双向反射分布函数 (Bidirectional Reflectance Distribution Function, BRDF)。这是描述材质的核心函数。它回答了这样一个问题:“对于从 方向射入的光,有多少能量会被反射到 方向?”。 BRDF 的具体形式决定了材质的质感 (例如,漫反射、镜面反射、金属感等)。
理论与现实的鸿沟:真实世界光照的复杂性
渲染方程在理论上是完美的,但直接求解它来渲染一个真实的游戏场景,在计算上是不可行的。因为真实世界的光路传播极其复杂。
-
核心观点: 真实场景中的光线传播路径千变万化,包括直接光、间接光、阴影、反射、折射等多种复杂现象。这些现象都包含在渲染方程的积分项中,使得其实时求解成为一个巨大的挑战。
-
复杂的光照现象:
- 直接光照 (Direct Lighting): 光源直接照射到物体表面。
- 阴影 (Shadow): 物体遮挡了光源,导致某些区域无法被直接照亮。
- 间接光照 (Indirect Lighting): 光线从一个物体表面反弹后,再照亮另一个物体。这是实现 全局光照 (Global Illumination, GI) 的关键。
- 颜色溢出 (Color Bleeding): 带有颜色的表面会将它的颜色“传递”给周围的物体,是间接光照的典型现象。
- 镜面反射 (Glossy/Specular Reflection): 在光滑物体(如镜子、水面)上形成的清晰反射。
- 折射/透射 (Refraction/Transmission): 光线穿过透明或半透明材质(如玻璃、水)时发生的路径偏折。
实时渲染面临的第一个挑战:可见性 (Visibility)
既然无法完整求解渲染方程,游戏引擎必须找到高效的近似方法。而要计算光照,首先要解决一个最基本的问题:一个点到底能不能被某个光源照到?
-
核心观点: 在渲染方程中,判断入射光 是否为零(即是否被遮挡)是计算光照的第一步。这个问题在图形学中被称为 可见性 (Visibility) 问题,其在游戏中最直观、最普遍的表现就是 阴影 (Shadow)。
-
阴影的挑战:
- 重要性: 阴影是提升场景真实感和空间感的关键视觉元素,几乎是所有现代游戏的标配。
- 实现难度: 讲座中引用了业界一句玩笑话 "Shadow is a Bitch",形象地说明了阴影实现的极端困难。
- 难点在于:
- 计算开销大: 判断场景中每个像素与每个光源之间的遮挡关系,计算量巨大。
- 质量问题多: 容易产生锯齿(Aliasing)、不精确(Peter Panning)、自遮挡错误(Shadow Acne)等各种视觉瑕疵。
- 没有银弹: 不存在一种能完美解决所有场景、所有光照情况的阴影技术。开发者需要根据具体需求,在多种充满妥协(Hacks)的技术中进行选择和组合。
渲染方程带来的三大挑战与实践简化
在上一部分我们了解了渲染方程(The Rendering Equation)是现代图形学的理论基石。然而,从理论到实践,这个看似优雅的方程给我们带来了三大核心挑战。本节将深入剖析这三大挑战,并探讨在实时渲染领域,我们是如何通过巧妙的简化来应对这些挑战的。
挑战一:复杂的光照输入 (Incoming Irradiance)
渲染方程的第一步是需要知道在场景的任意一点,从所有方向接收到的光照信息。这本身就是一个极其困难的问题,主要体现在两个方面:
1. 光的可见性 (Visibility) - 阴影的难题
- 核心观点:计算一个点是否能被光源照亮,本质上是一个 可见性(Visibility to light) 问题。这直接导致了渲染中最棘手的问题之一: 阴影(Shadows)。
- 关键挑战:虽然概念简单,但在实践中生成高质量、无瑕疵的阴影极其困难。它常常需要大量的 Hacks 和特殊处理,解决了一种情况下的问题,往往会引发其他情况的 Bug。
- 重要性:阴影对于人类大脑感知物体的空间层次、深度和相对位置至关重要。没有阴影的场景会显得“飘”且不真实。
2. 光源自身的复杂性 (Light Source Complexity)
- 核心观点:真实世界的光源形态各异,远比简单的数学模型复杂。
- 光源类型:
- 简单光源:如 方向光 (Directional Light) 、 点光源 (Point Light) 和 聚光灯 (Spotlight),这些在实时渲染中相对容易处理。
- 复杂光源:如 面光源 (Area Light)。面光源的引入会使问题复杂度急剧升高,因为光源自身的旋转和形态都会极大地影响着色结果,产生柔和的阴影(软阴影),这对于简单的可见性测试来说非常困难。
关键术语定义
为了精确描述光,图形学中有两个基础且核心的“黑话”:
- Radiance (辐射度): 指的是从一个表面发出或反射出去的光的能量和分布,单位是 。可以理解为“出射的光”。
- Irradiance (辐照度): 指的是一个表面接收到的所有入射光能量的总和,是对半球空间上所有方向的 Incoming Radiance 进行积分的结果。可以理解为“入射的光”。
挑战一的本质,就是我们难以精确、高效地计算出场景中每一点的 Irradiance。
挑战二:光与材质的复杂交互 (Shading Integral)
即使我们已经知道了所有方向的入射光(Irradiance),第二个挑战也随之而来:如何计算这些光与物体表面材质交互后的最终效果。
-
核心观点:这个交互过程由渲染方程中的积分来描述,我们需要将覆盖整个半球的入射光()与材质的双向反射分布函数(BRDF)相乘,然后进行积分。
-
渲染方程 (简化形式):
- : 出射的Radiance(我们最终看到的光)。
- : BRDF,描述了材质的反射特性。
- : 入射的Radiance(来自挑战一)。
- : 在以法线 为中心的半球上进行积分。
-
关键挑战:这个积分在计算上是极其昂贵的。对于实时应用(如游戏),逐点、逐像素地进行暴力数值积分(例如,蒙特卡洛采样)是完全不可行的。因此,如何 快速、近似地求解这个积分,是实时渲染中被称为 Shading 的核心难题。
挑战三:无处不在的间接光照 (Global Illumination)
这是最让渲染工程师头疼的问题,它让前两个挑战的难度呈指数级增长。
- 核心观点:在真实世界中,光线会在物体表面之间 多次反弹(Bouncing)。这意味着, 场景中的每一个物体,一旦被照亮,其自身就变成了一个新的光源。
- 关键影响:
- 一个点的光照不仅来自主光源(直接光照),还大量来自于周围环境反射过来的光(间接光照 / 全局光照 Global Illumination)。
- 这形成了一个恶性循环:为了计算A点的光照,你需要知道B点反射过来的光;而要计算B点的光照,你又可能需要知道A点反射出去的光。这是一个无限递归的过程。
- 经典案例: 康奈尔盒子 (Cornell Box)。这个经典的测试场景通过两个不同颜色的墙壁,清晰地展示了光线多次反弹后产生的 色彩溢出(Color Bleeding) 等复杂光影效果。它常被用作衡量各种全局光照算法准确性的 “基准真相 (Ground Truth)”。
- 算法挑战:早期的 光线追踪 (Ray Tracing) 算法试图通过递归追踪光线来模拟这一过程,但这会导致光线数量爆炸性增长,即使在离线渲染中也难以承受。
从理论到实践:实时渲染的简化之道
既然完整求解渲染方程如此困难,那么在性能受限的游戏引擎中,我们是如何“投机取巧”的呢?答案是:简化。
我们不直接求解复杂的积分和递归,而是将问题分解成几个可以被硬件快速处理的、简化的部分。
-
简化光源模型:
- 主光源 (Dominant Light):场景中只设定一个或少数几个简单的光源(方向光、点光等)作为主要光照来源,计算其直接光照和阴影。
- 环境光 (Ambient Light):用一个极其简化的模型来模拟所有复杂的间接光照。最简单粗暴的方式就是一个恒定的颜色值/强度,即 Ambient Light,它假设所有间接光都是均匀的。
-
简化反射模型:
- 核心问题:如何模拟物体(尤其是光滑表面)对周围环境的反射?
- 经典Hack:使用 环境贴图 (Environment Map)。这是一种预先捕捉或生成的、记录了场景特定位置周围360度环境信息的贴图(通常是立方体贴图 Cube Map)。当需要计算反射时,引擎不去追踪真实的光线,而是根据反射向量去这个贴图里“查询”颜色。这是一种非常高效的近似方法,极大地简化了对环境反射的模拟。
通过这些简化,我们虽然牺牲了物理的完全精确性,但却能在有限的硬件资源和时间内,创造出令人信服的、足够逼真的实时渲染效果。这也是游戏渲染技术发展的核心思路: 在真实性、性能和艺术效果之间寻找最佳平衡点。
从经典光照到材质模型的演进
在理解了渲染方程的理论框架后,本部分将深入探讨在算力有限的早期,图形学工程师们如何通过巧妙的简化和“经验主义”方法,构建出影响深远的经典光照与材质模型,并初步涉及阴影的实现思路。
1. 对渲染方程的早期简化与实践
面对 Kajiya 渲染方程这个庞大而复杂的半球积分,早期的实时渲染无法直接求解。工程师们采用了一种“分而治之”的策略,将复杂的光照环境拆解为几个可以简单模拟的部分。
核心观点
早期的实时光照模型本质上是对渲染方程的一种高度简化的近似。它将无穷无尽的环境光分解为三个核心组件,用“土办法”解决了关键的视觉表现问题。
关键组件
-
环境光 (Ambient Light):
- 目的: 模拟来自环境的、无处不在的间接光照。
- 实现: 用一个 全局统一的、强度较低的颜色值 来代表,直接叠加到物体上。这可以看作是对渲染方程中半球积分项的一个极度简化的常数近似。
-
主光源 (Dominant Light):
- 目的: 模拟场景中起主导作用的单一强光源,如太阳或灯泡,它能产生明显的明暗对比和高光。
- 实现: 通常是方向光 (Directional Light) 或点光源 (Point Light),计算方式直接、开销小。
-
高频反射 (High-frequency Reflections):
- 问题: 对于光滑表面(如镜子、金属),如何模拟其对周围环境的清晰反射?这部分信息在环境光和主光源中都丢失了。
- 解决方案: 引入 环境贴图 (Environment Map),通常是一个立方体贴图 (Cube Map)。
- 工作原理:
- 将场景的六个方向(前、后、左、右、上、下)的图像预渲染或捕捉到一张立方体贴图上。
- 在渲染物体表面时,根据 视角方向 (View Vector) 和 表面法线 (Normal Vector) 计算出反射向量。
- 用这个反射向量去立方体贴图中采样,得到的颜色就是该点的环境反射颜色。
- 意义: 这个方法巧妙地将渲染方程中与 BRDF 的高光项 (Specular Lobe) 强相关的部分单独剥离出来,用一次贴图查找高效地解决了高光反射问题。
2. 材质模型的发展:经验派与 Blinn-Phong
材质决定了光线与物体表面如何交互,即 BRDF 的具体形态。在材质模型的发展史上,出现了一个非常重要且实用的流派—— 经验派 (Empirical School)。
核心观点
经验派模型不追求完全的物理正确性,而是通过观察现实世界,用简单、可控的数学函数来“模仿”光照现象,以达到在视觉上可信且计算开销低的效果。 Blinn-Phong 模型 是这一派的杰出代表。
Blinn-Phong 模型详解
Blinn-Phong 模型将材质的视觉表现分解为两个线性可叠加的部分:漫反射和高光。
-
光可叠加原理 (Principle of Superposition): 这是 Blinn-Phong 模型以及许多光照模型成立的基础物理假设。它指出,来自不同光源的光在某一点产生的效果,等于每个光源单独作用时效果的线性总和。因此,我们可以简单地将漫反射和高光分量相加。
-
漫反射项 (Diffuse Term):
- 现象: 模拟光线射入物体表面后,向各个方向均匀散射的效果。其亮度只与光线入射角度有关,与观察角度无关。
- 实现: 通常使用 Lambertian 模型,亮度与光线方向
L和表面法线N夹角的余弦成正比。
Diffuse = k_d * lightColor * max(0, dot(N, L))k_d: 材质的漫反射颜色(或称为反照率 Albedo)。
-
高光项 (Specular Term):
- 现象: 模拟光滑表面(如塑料、金属)上出现的亮斑,其形状和强度与观察角度密切相关。
- 实现: 使用一个 Power 函数 (幂函数) 来控制高光的范围和锐利度。这是经验派的精髓所在。
Specular = k_s * lightColor * pow(max(0, dot(N, H)), shininess)k_s: 材质的高光颜色。H: 半程向量 (Halfway Vector),是光线方向L和视角方向V的角平分线方向。shininess: 高光指数,一个常数。值越大,pow函数的曲线越陡峭,产生的高光点越小、越锐利,模拟的表面也越光滑。
Blinn-Phong 模型的两大局限性
尽管 Blinn-Phong 模型简单、高效,并且在很长一段时间内统治了实时渲染领域,但它存在两个致命的缺陷。
-
能量不守恒 (Not Energy Conserving):
- 问题: 在某些参数组合下(如过高的
k_d和k_s),模型计算出的出射光能量可能会超过入射光能量。 - 术语辨析: 讲座中特别强调,更准确的说法是 “能量不保守 (Not Energy Conservative)”。物理正确的光照模型应该是能量保守的,即出射能量必须小于等于入射能量(因为部分能量会被表面吸收),而不是严格相等(守恒)。
- 危害: 在单次渲染中问题不明显,但在需要多次光线反弹的算法中(如 光线追踪 Ray Tracing),这种能量的微小增长会逐次累积放大,导致渲染结果出现严重错误(例如,一个封闭黑盒内部因为能量凭空增加而变得异常明亮)。
- 问题: 在某些参数组合下(如过高的
-
缺乏物理真实感 (Lacks Physical Realism):
- 问题: Blinn-Phong 的参数 (
k_d,k_s,shininess) 与真实的物理材质属性没有直接对应关系。美术师只能依靠经验和试错来调节,难以稳定地创作出各种不同质感的材质。 - “万物皆塑料”: 这是一个经典调侃。由于其模型的局限性,无论如何调节参数,用 Blinn-Phong 渲染出的物体(无论是木头、石头还是金属)往往都带有一种挥之不去的 “塑料感”。
- 对比: 现代的 PBR (Physically Based Rendering) 材质模型 通过引入粗糙度 (Roughness)、金属度 (Metallic) 等与物理属性直接挂钩的参数,能够更精准、更真实地表现大千世界的各种材质。
- 问题: Blinn-Phong 的参数 (
3. 可见性与阴影:Shadow Map 的崛起
阴影是提升场景真实感和空间感的关键元素。
核心观点
阴影的本质是一个可见性问题:对于场景中的某一个点,它是否能够被光源“看到”? 如果看不到,它就处于阴影之中。
发展与选择
- 百花齐放的早期: 在图形学早期,涌现了大量阴影算法,如 Shadow Volume (阴影锥) 、 Perspective Shadow Maps 等。
- 游戏行业的坚定选择: 尽管算法众多,但在过去十几二十年的游戏行业发展中, Shadow Map (阴影贴图) 凭借其相对简单的实现、稳定的效果和对硬件的友好性,成为了事实上的行业标准,并在此基础上衍生出无数的改进技术。
从经典三件套到 AAA 游戏的图形技术演进
一、 阴影技术的核心基石:Shadow Map
在图形学的历史长河中,阴影生成技术百花齐放,例如 Shadow Volume、Perspective Shadow Maps 等。然而,在游戏行业过去近二十年的发展中, Shadow Map 凭借其直观和相对高效的特性,成为了绝对的主流和基石。
1.1 核心思想
Shadow Map 的思想非常直接且巧妙:通过模拟光源的视角来判断物体的可见性。
- 核心观点:如果一个点从主摄像机视角能看到,但从光源的视角却被其他物体挡住了,那么这个点就处于阴影之中。
- 关键术语: Shadow Map (阴影贴图),本质上是一张从光源视角渲染的 深度图 (Depth Map)。
算法流程概览
-
生成阶段 (Light Pass):
- 将摄像机放置在光源位置,朝向场景进行渲染。
- 此过程不关心颜色、材质等信息,只将离光源最近的物体的深度值写入一张纹理中。这张纹理就是 Shadow Map。
-
渲染阶段 (Camera Pass):
- 正常从玩家的摄像机视角渲染场景。
- 对于场景中的每一个需要计算光照的片元 (Fragment),将其坐标 反向投影 (Reproject) 到光源的裁剪空间中。
- 计算出该片元到光源的距离
d_current。 - 查询 Shadow Map 中对应位置存储的深度值
d_shadowmap(即该方向上离光源最近的遮挡物的距离)。 - 深度比较:
- 如果
d_current > d_shadowmap,意味着当前片元在遮挡物之后,处于阴影中。 - 如果
d_current <= d_shadowmap,意味着当前片元就是那个最近的物体(或在它之前),处于光照中。
- 如果
1.2 核心挑战与妥协 (Hacks)
尽管思想简单,Shadow Map 在实践中面临诸多问题,这些问题源于光源视角采样率与相机视角采样率的不匹配。
-
主要问题:
- 走样 (Aliasing):Shadow Map 分辨率有限,导致阴影边缘呈现锯齿状。
- 自遮挡 (Self-Shadowing) / 阴影粉刺 (Shadow Acne):由于浮点数精度限制,一个表面上的点在进行深度比较时,可能会被误判为在自己产生的阴影之下,导致表面出现不正确的条纹状阴影。
- 透视走样 (Perspective Aliasing):当一个很大的多边形以很小的角度朝向光源时,它在 Shadow Map 中只占很小的区域,导致阴影精度严重不足。
-
经典解决方案 (Hack):
- 阴影偏移 (Shadow Bias):在进行深度比较时,给从 Shadow Map 中采样到的深度值
d_shadowmap增加一个微小的偏移量 (Bias),人为地将表面“推”离阴影,以避免自遮挡。 - 副作用:Bias 会导致一个新问题—— Peter Panning,即物体与其阴影分离,看起来像是“浮”在空中,最常见的就是角色脚底的阴影与脚分离。
- 阴影偏移 (Shadow Bias):在进行深度比较时,给从 Shadow Map 中采样到的深度值
1.3 极限场景:地平线附近的低角度光照
这是 Shadow Map 技术最头疼的场景,也是艺术家最偏爱的场景之一(例如“夕阳残血”的氛围)。
- 核心难点:当光源(如太阳)靠近地平线时,阴影会被极度拉长。这意味着 Shadow Map 上的一个像素需要覆盖巨大的世界空间范围,导致阴影分辨率急剧下降,各种 Artifacts 会被无限放大。
- 业界实践:为了解决这个问题,现代游戏引擎甚至会准备多套阴影算法。例如,当太阳角度较高时使用算法 A,当太阳落到地平线附近时,平滑地过渡到专门处理长阴影的算法 B。
二、 上个时代的渲染“三件套”:经典但有效的组合拳
将 Shadow Map 与其他简化技术结合,就构成了上一个时代(大约10-15年前)游戏渲染的经典“三件套”。这个组合通过一系列 Hack,巧妙地绕过了渲染方程的复杂性。
2.1 组合方案回顾
- 直接光:使用简单的点光源或方向光模型。
- 间接光/环境光:用一个全局的 环境光遮蔽 (Ambient Occlusion) 常量,加上一张 环境贴图 (Environment Map) 来模拟粗糙的反射和环境光。
- BRDF:使用 Blinn-Phong 等经验模型,将复杂的BRDF积分简化为几个简单的多项式计算。
- 可见性/阴影:使用 Shadow Map 技术。
2.2 “五九改”的比喻:老技术的新生命
这个经典组合就像是“五九改”坦克——虽然基础老旧,但通过不断地修改和优化,在特定场景下依然非常有效。
- 核心观点:这套技术是理解现代渲染管线的基础。即使在今天,它仍然是 移动端、低配硬件 或需要极致性能优化时的首选方案。 先掌握好这个基础,才能更好地理解后续更先进的技术。
三、 AAA 游戏的崛起与技术革新
随着硬件性能的提升,尤其是 可编程着色器 (Programmable Shaders) 的出现,AAA 游戏行业开始不满足于“三件套”的效果,开启了对图形技术极限的不断探索。
3.1 AAA 文化的驱动力
- 核心特质:“自己给自己找麻烦”。AAA 行业的工程师们有一种执念,即不断挑战技术边界,创造出与众不同、令人惊叹的视觉效果,从而推动整个行业的技术进步。
3.2 视觉演进的实例:《刺客信条》系列
通过对比15年前的初代《刺客信条》和近年的续作(如《起源》、《英灵殿》),可以直观地感受到游戏图形在光照、材质和场景复杂度上的巨大飞跃。
3.3 新思路的提出:预计算 (Pre-computation)
为了突破实时渲染的性能瓶颈,解决更复杂的光照问题(尤其是全局光照),业界引入了一个核心思想:预计算。
- 核心观点:既然场景中的大部分物体(建筑、地形)和某些光源(如特定关卡中的太阳)是静态的,那么它们之间复杂的光照交互就可以 离线提前计算 (Offline Pre-computation),并将结果存储下来。在游戏运行时,直接加载和使用这些预计算好的数据即可。
- 理论基础:这是计算机科学中经典的 “空间换时间” (Space-Time Tradeoff) 策略。通过消耗更多的存储空间(硬盘和内存)来换取运行时的宝贵计算时间。
这个思路为解决复杂的全局光照问题打开了一扇新的大门,也是下一阶段技术演进的核心。
预计算全局光照与球谐函数
在实时渲染中,完整的光照计算(尤其是间接光照)开销巨大。这一部分探讨了如何利用预计算(Precomputation)来解决这个问题,并引入了实现这一目标的核心数学工具——球谐函数(Spherical Harmonics)。
一、 问题的提出:实时全局光照的挑战
为了在游戏中实现逼真的光照效果,我们需要模拟光线的多次反弹。然而,实时计算这种复杂光照的成本极高,因此业界普遍采用一种“空间换时间”的策略,即 预计算(Precomputation)。
-
空间换时间 (Space-for-Time Tradeoff):
- 这是一个经典的计算机科学思想。在图形学中,它意味着我们花费大量的离线时间去计算和存储光照信息,以换取在运行时(Runtime)能够极快地查询和使用这些信息,从而达到实时的效果。
- 这适用于场景中大部分静态的元素,如固定的场景几何体和光源(例如,关卡中锁定的太阳位置)。
-
全局光照 (Global Illumination, GI):
- 定义: 指包含了 直接光照(Direct Lighting) 和 间接光照(Indirect Lighting) 的完整光照模型。间接光照是光线在场景中经过一次或多次反弹后到达物体表面的部分。
- 重要性: GI是实现视觉真实感的关键。
- 无GI: 场景中只有被直接照亮的地方是亮的,阴影区域一片死黑。即使通过增加一个恒定的环境光(Ambient Light)来提亮暗部,整个场景也会显得非常“平”,缺乏立体感和层次感。这是许多早期游戏室内场景看起来不真实的主要原因。
- 有GI: 能够模拟光线从地面反弹到天花板,或从红色墙壁反射出带有红色的光,使整个场景的光照过渡更柔和、色彩更丰富,极大地提升了沉浸感。
-
实时GI面临的两大挑战:
- 数据量问题: 对于场景中的任意一点,其接收到的间接光来自四面八方(一个完整的球面)。如果为场景中每个位置都存储一张高分辨率的环境贴图(Environment Map),数据量将是天文数字。
- 计算量问题: 在运行时,要计算某个像素的最终颜色,需要将该点接收到的球面光照函数与其材质的BRDF进行复杂的积分运算(即 卷积 (Convolution))。对屏幕上的每个像素都执行这种操作(例如,通过蒙特卡洛方法在球面上进行上百次采样)是完全不现实的。
二、 解决方案的灵感:傅里叶变换与频域思想
核心观点:
直接处理球面上的光照函数(空间域)既复杂又缓慢。我们可以借鉴信号处理中的思想,将这个函数转换到另一个“域”(频域)中进行处理,从而实现高效的压缩和计算。傅里叶变换就是这种思想的绝佳范例。
关键术语与概念
-
傅里叶变换 (Fourier Transform):
- 一种强大的数学工具,可以将一个信号(如图像、声音)从其原始域(如空间域、时域)转换到 频域 (Frequency Domain)。
- 它将复杂的信号分解为一系列不同频率的正弦/余弦波的叠加。
-
频域思想带来的两大优势:
-
高效的数据压缩 (Efficient Data Compression):
- 大部分自然信号(包括光照)的能量都集中在低频部分。
- 通过在频域中仅保留少数低频部分的系数,我们就可以得到原始信号的一个很好的近似。
- 例子: 一张
200x200的图像可能需要数万个像素数据来存储,但我们可能只需要几十个频域系数就能大致还原出图像的轮廓。这是一种非常高效的压缩方式。
-
简化的卷积运算 (Simplified Convolution):
- 这是最关键的数学性质。两个函数在空间域中的卷积,等价于它们在 频域中的逐元素相乘(点积)。
- 这意味着,原本极其耗时的积分运算,在转换到频域后,可以变成一个非常简单的乘法运算,计算复杂度大大降低。
-
三、 球谐函数 (Spherical Harmonics):图形学中的“球面傅里叶变换”
核心观点:
球谐函数 (Spherical Harmonics, SH) 就是傅里叶变换思想在球面上的具体应用。它提供了一组标准化的 基函数 (basis functions),任何定义在球面上的函数(如入射光分布)都可以被分解成这些基函数的线性组合。
关键术语与概念
-
球谐函数 (Spherical Harmonics, SH):
- 可以理解为定义在球面上的“正弦和余弦”。它们是一组正交的基函数,非常适合用来表示球面数据。
- 历史贡献: 由 Peter-Pike Sloan 在微软工作时引入图形学领域,并提出了著名的 预计算辐射度传输 (Precomputed Radiance Transfer, PRT) 框架,奠定了SH在实时渲染中的应用基础。
-
SH基函数简介:
- SH函数按“阶 (band)”来组织,阶数越高,表示的频率越高,细节越丰富。
- 零阶 (l=0, 1个系数): 是一个常数。它代表了整个球面函数的平均值,类似于一个恒定的环境光。
- 一阶 (l=1, 3个系数): 对应三个非常简单的线性函数。它们可以被直观地理解为与单位球上一点的 X, Y, Z 坐标 成正比。这三个基函数可以表示来自三个正交方向(X, Y, Z轴)的定向光照。
- 二阶 (l=2, 5个系数): 对应更复杂的二次多项式,可以表达更复杂的光照分布。
- 可视化: SH基函数在球面上通常有正有负(图中绿色为正,红色为负),通过它们的线性组合可以拟合出任意形状的球面函数。
通过将复杂的光照环境投影到前几阶(通常是前2阶或3阶,即4个或9个系数)的SH基函数上,我们就能用极少量的数据(几个浮点数)来近似表示一个低频的光照环境,并能以极高的效率完成光照的卷积计算。这正是预计算全局光照技术的核心。
球谐函数与现代光照技术
在这一部分,我们将深入探讨一个在现代实时渲染中至关重要的数学工具—— 球谐函数 (Spherical Harmonics, SH),并了解它如何彻底改变了游戏中的全局光照,特别是 Lightmap 技术的实现。
一、球谐函数 (Spherical Harmonics) 的核心特性
球谐函数是一组在球面上定义的特殊函数,它们可以被看作是傅里叶变换在球面上的模拟。通过将这些基函数线性组合,我们可以用少量系数来近似表示定义在球面上的任意复杂函数,例如一个点的入射光照信息。
1.1 直观理解:从基函数到原子轨道
-
基函数的可视化:
- 零阶 (L0): 是一个完美的球体,代表了来自所有方向的平均光强。
- 一阶 (L1): 形状像两个在对立方向上鼓起的“泡泡”,一个为正(绿色),一个为负(红色)。这三个基函数(分别沿X, Y, Z轴)可以有效地表示一个主导的光照方向。
- 高阶 (L2, L3...): 随着阶数升高,函数的形状变得越来越复杂和“魔幻”,能够表达更高频率的光照细节。
-
与物理世界的惊人巧合:
- 球谐函数的形状与氢原子的电子云轨道分布几乎完全一致。这揭示了其背后深刻的数学与物理联系,也说明了它是一种描述自然现象的和谐而基础的工具。
1.2 关键数学属性
-
正交性 (Orthogonality):
- 任意两个不同的球谐基函数在球面上的积分为零。这个特性使得我们可以轻松地将一个球面函数投影到这组基上,并独立计算出每个基函数对应的系数,而不会相互干扰。
-
平滑性 (Smoothness):
- 球谐函数的 拉普拉斯算子(二阶导数)恒为零。这意味着函数本身是无限光滑的,没有任何尖锐的变化。这使得它成为表达低频信号(如柔和的环境光)的理想工具。
二、球谐函数在游戏光照中的应用
2.1 低频光照的完美表达
游戏中的环境光,尤其是移除了太阳等主光源后的间接光照,其主要特征是低频的——光照变化缓慢、柔和,没有硬朗的阴影。球谐函数正是为此而生,可以用极少的几个系数就准确地捕捉到这种低频光照的整体感觉。
2.2 实践中的权衡:阶数与精度
- 阶数选择:
- 在早期的游戏中(如 Halo),可能会使用到 二阶或三阶SH 来获得更精确的方向信息。
- 在现代很多引擎中,为了极致的性能和存储效率,通常只使用到 一阶SH (即L0和L1,共4个基函数)来编码环境光。
- 效果:
- 即便只用一阶SH,重建出的环境光贴图虽然模糊,但它准确地保留了光线的主要方向和强度,对于计算漫反射效果已经完全足够。
2.3 核心优势:高效的存储与计算
这是SH在游戏引擎中被广泛应用的核心原因。
-
存储压缩:用一个像素的代价存储整个环境光
- 参数数量: 一阶SH包含4个基函数。对于彩色光照,我们需要为R, G, B三个通道分别存储系数,总计 4 (系数) × 3 (通道) = 12个参数。
- 智能压缩策略 (以 Days Gone 引擎为例):
- L0 (零阶系数): 代表平均光强,是 HDR 数据。使用 BC6H 这样的HDR压缩格式单独处理。
- L1 (一阶系数): 代表方向光,其动态范围相对较小,是 LDR 数据。可以使用 BC7 或其他LDR格式压缩。
- 惊人的效率: 通过这种混合压缩,存储一个点的完整球面光照信息(一个Light Probe)最终可能只需要 32 bits。这相当于一个普通
RGBA8像素的存储开销,实现了用一个像素的成本存储整个环境光信息的壮举。
-
计算简化:卷积变点积
- 核心原理: 在球面上对两个函数(例如,入射光照函数和材质的BRDF函数)进行 卷积 (Convolution) 运算,可以等价转换为它们各自的 球谐系数向量进行点积 (Dot Product)。
- 巨大优势: 这将一个复杂、耗时的积分运算,简化成了一个极其简单和快速的向量点积。这使得在运行时实时计算一个物体表面接收到的漫反射光照变得非常高效。
- 注意点: 在实际实现时,需要注意公式中的各种归一化因子(例如
π),否则会导致结果错误。
三、终极应用:现代全局光照 Lightmap
球谐函数的出现,让古老的 Lightmap 技术焕发了新生,使其成为实现高质量静态全局光照的主流方案。
3.1 Lightmap 的演进
- 早期 (Quake时代): 由 约翰·卡马克 (John Carmack) 提出,最初的Lightmap主要用于预计算静态阴影,存储的是一个标量光照值。
- 现代 (GI时代): 在 Peter-Pike Sloan 提出将SH应用于光照之后,Lightmap技术被彻底革新。现在,Lightmap的每个纹素(texel)不再存储一个简单的颜色值,而是存储一组 SH系数。这使得Lightmap能够记录下每个点的方向性光照信息,从而可以正确地计算出法线对光照的影响,得到高质量的漫反射甚至部分高光效果。
3.2 Lightmap Atlas 的生成流程
为了将整个场景的光照信息烘焙到一张或几张贴图中,引擎需要执行一个复杂的过程来生成 Atlas (地图集)。
-
Atlas: 将场景中多个独立物体的UV展开并打包到一张巨大的纹理上的技术。
-
核心步骤:
- 几何简化 (Geometry Simplification): 通常会为Lightmap准备一套简化的模型,因为光照信息是低频的,不需要过于精细的几何细节。
- 参数化 (Parameterization / UV Unwrapping): 这是最关键也最复杂的一步。需要将三维模型的表面不失真地展开成二维的UV坐标。这个过程非常复杂,DirectX甚至曾为此专门提供过API。
- 均匀的纹素分布 (Uniform Texel Distribution): 一个好的Lightmap Atlas应该保证,在3D世界中相同面积的表面,在最终的Atlas贴图上也分配到差不多大小的纹素区域。这确保了整个场景的光照贴图精度是均匀的。
深入全局光照:Lightmap 与 Light Probe 技术剖析
在这一部分,我们将深入探讨两种在游戏中实现高质量静态全局光照(Global Illumination, GI)的经典技术: Lightmap 和 Light Probe。讲座的核心不仅仅是介绍技术本身,更在于剖析其背后蕴含的、至今仍在影响现代渲染架构的核心思想。
一、Lightmap 技术详解
Lightmap 是一种将复杂的光照计算结果预先烘焙(Bake)到纹理上的技术,以极低的运行时开销换取高质量的静态光照效果。
核心前提:场景参数化 (Parameterization)
- 核心观点: 要使用Lightmap,必须先将场景中复杂的三维模型表面,展开成一个 二维的纹理坐标空间(UV)。这个过程称为参数化或 UV展开 (UV Unwrapping)。
- 关键目标: 理想的参数化展开,应该让模型表面上的每一个区域,在展开后的UV图上所占的面积比例保持均匀。如下图所示,当把不同颜色的格子反向投影回三维世界时,每个格子的大小应大致相等。这确保了光照贴图的精度在模型各处是均匀的。
- 技术难点: 实现高质量的自动UV展开是一个非常复杂的数学问题。讲座中提到,DirectX 甚至在十几年前专门为此开发过一个API,但工业界在使用中也遇到了不少问题。
烘焙过程与惊艳效果
- 烘焙 (Baking): 这是一个计算量巨大的离线过程。
- 美术在场景中布置好模型和光源后,点击“烘焙”按钮。
- 计算任务会被分发到一个由多台高性能计算机组成的 “光照农场” (Light Farm)。
- 整个过程耗时漫长,通常需要半小时到数小时,在此期间美术无法进行迭代,严重影响开发效率。
- 效果对比:
- 仅有Lightmap (GI): 由Lightmap提供的间接光照。可以清晰地看到光线在场景中多次反弹(bouncing)后形成的效果,以及物体之间非常柔和、自然的 软阴影 (Soft Shadows)。
- Lightmap + 直接光: 当叠加上主光源(Dominant Light)的直接光照后,整个场景的光影关系变得非常饱满和真实。
- 重要性: 如果没有Lightmap提供的GI信息,场景中未被直接光照到的地方将是纯黑的,完全丢失几何细节,画面会显得非常“平”和“假”。 GI对于3A游戏的真实感至关重要。
优缺点分析
-
优点:
- 极高的运行时性能: 运行时,渲染一个Lightmap的成本约等于多采样一张纹理,开销极低。
- 极高的视觉质量: 离线计算没有时间限制,可以运行非常复杂和精确的光线追踪算法,从而产生极其细致、微妙(subtle)的光影效果,深受美术喜爱。
-
缺点:
- 超长的预计算时间: 烘焙过程耗时极长,是开发流程中的一个巨大瓶颈。
- 完全静态: Lightmap只能处理 静态物体 (Static Objects) 和 静态光源 (Static Lights)。一旦场景中的物体或光源发生移动,之前烘焙的所有光照信息都会失效,必须重新烘焙。
- 对动态物体的融合难题: 动态物体无法拥有预烘焙的Lightmap。传统的Hack方法(如在物体脚下采样Lightmap颜色)效果很差,经常出现“角色走进烘焙好的阴影里突然变黑”的穿帮问题。
- 巨大的存储开销: Lightmap本质是纹理,会占用大量的显存和磁盘空间(通常为几十到几百MB),这正是其“空间换时间”策略的代价。
超越技术本身:两大核心思想
尽管Lightmap技术可能在未来被新技术取代,但它蕴含的两个核心思想非常宝贵,值得每一位引擎开发者深入理解:
-
空间换时间 (Space-for-Time Trade-off)
- 核心: 将极其耗时的计算(光照)提前在离线阶段完成,并将结果(光照贴图)存储起来,以换取运行时的超高性能。这是图形学和计算机科学中一种普适的优化思想。
-
将复杂空间参数化 (Parameterization of Complex Space)
- 核心: 将一个不规则、复杂的三维几何场景,通过数学方法映射(或说“拍平”)到一个规则、易于管理和计算的数据结构上(如二维纹理)。这种“规整化”的思想,使得许多原本棘手的计算问题变得可行。
二、Light Probe:空间换时间的另一种思路
既然将表面参数化到2D纹理如此困难,一个更直接的想法是:直接在三维空间中进行采样。这就是 Light Probe(光照探针)技术。
基本原理
- 核心观点: 不再对物体的“表面”进行参数化,而是对“空间体积”进行离散化采样。
- 实现方式: 在场景空间中,沿着玩家可能经过的路径或重要区域,放置一系列的采样点,我们称之为 光照探针 (Light Probe)。
- 采样内容: 每一个探针都会在离线烘焙阶段,捕捉并存储其所在位置 来自所有方向(360°)的光照信息 (通常存成一个CubeMap或者球谐函数系数)。
运行时工作方式
- 动态物体的光照: 当一个动态物体(如赛车、角色)在场景中移动时:
- 引擎会找到离该物体 最近的几个Light Probe。
- 根据物体与这些探针的相对位置,对它们的 光照信息进行插值 (Interpolation)。
- 将插值得到的光照结果,应用到这个动态物体上。
- 空间数据结构: 为了快速找到邻近的探针并进行插值,通常会将所有探针构建成一个空间加速结构,例如由多个 四面体 (Tetrahedron) 组成的网格。当物体进入某个四面体时,就可以利用其四个顶点的探针信息进行重心坐标插值。
核心挑战:探针的放置 (Probe Placement)
- 早期方法: 美术手动放置。这种方法非常直观,但缺点是工作量巨大、极易出错,且每次关卡修改都需要重新调整,维护成本极高。
- 现代方法: 自动化生成。现代引擎倾向于采用算法自动放置探针。
- 基本流程:
- 在空间中初步均匀撒点。
- 根据玩家可达区域、场景几何结构等信息进行筛选和调整,确保探针分布在有意义的位置。
- 向外进行一定的延拓,以覆盖更多区域。
- 目标: 实现探针的合理、高效覆盖,减少人工干预。
- 基本流程:
总结: 这一部分我们学习了Lightmap和Light Probe。Lightmap通过参数化表面实现了极致的静态光照质量和运行时性能,但代价是漫长的烘焙时间和完全的静态限制。Light Probe则转换思路,通过离散化空间来为动态物体提供高质量的间接光,其挑战在于如何智能地放置探针。两者共同体现了图形学中“空间换时间”和“将复杂问题规整化”的宝贵思想。
从动态全局光照探针到PBR材质理论
在上一部分我们讨论了静态光照烘焙(Lightmap)之后,本次我们将深入探讨如何处理动态物体和高频反射,并由此引出构建现代真实感渲染的另一大基石——基于物理的材质(PBR)。
一、 动态全局光照方案:光照探针 (Light Probe)
Lightmap 效果虽好,但它对动态物体无能为力。为了让场景中的动态角色、移动道具也能融入环境光照,业界普遍采用 光照探针 (Light Probe) 技术作为补充和延伸。
1. 探针的部署:自动化是关键
- 传统痛点: 手动在场景中放置成百上千个光照探针是一项极其繁琐且容易出错的工作,是技术美术的噩梦。
- 现代方案: 自动化探针生成 (Automated Probe Generation)。
- 核心思路: 首先在空间中(尤其是在玩家可达区域)均匀或根据几何复杂度生成采样点。然后,以这些点为基础,结合建筑物等静态几何体进行空间延拓,最终在整个场景中相对均匀地“撒”下探针。
- 价值: 对于工业级生产流程,自动生成算法能极大提升效率和迭代速度,是现代引擎必备的功能。一个好的自动化工具能让美术团队的幸福感倍增。
2. 探针的分类与协作
为了平衡性能与效果,探针通常被分为两类,各司其职:
-
光照探针 (Light Probe / Irradiance Probe)
- 核心用途: 主要用于采样和存储 低频的漫反射光照 (Diffuse Lighting)。
- 特点:
- 部署密集: 为了光照过渡平滑,需要大量放置。
- 精度较低: 漫反射对信息频率不敏感,因此探针数据可以被高度压缩(例如使用球谐函数SH),以节省内存和带宽。
-
反射探针 (Reflection Probe)
- 核心用途: 专门用于捕捉和提供 高频的镜面反射信息 (Specular Reflection)。
- 特点:
- 部署稀疏: 通常只在关键位置或材质变化区域放置。
- 精度很高: 镜面反射对环境细节非常敏感,需要存储高分辨率的环境贴图(通常是 Cubemap),以保证反射的清晰度。
总结: 通过 密集的低精度光照探针 和 稀疏的高精度反射探针 协同工作,我们可以在性能可控的前提下,为场景中的动态物体提供相当不错的实时全局光照效果。
3. 探针的运行时更新 (Runtime Update)
Light Probe 相较于 Lightmap 的一个巨大优势是其可动态更新的能力。
-
更新原理:
- 在探针所在位置,模拟一个拥有六个方向的虚拟相机。
- 向六个方向(上、下、左、右、前、后)分别渲染场景,生成六张贴图。
- 将这六张图合成为一个 环境立方体贴图 (Cubemap)。
- 使用 GPU Shader 对 Cubemap 进行快速处理(如卷积生成辐照度图,或预滤波生成不同粗糙度的反射图)。
-
性能策略: 延迟更新 (Deferred Update)
- 运行时更新探针是一项高消耗操作,绝不能每帧都执行。
- 引擎通常会采用智能调度策略:
- 按需更新: 仅当相机或重要动态物体进入探针影响范围,或场景发生显著变化时才触发更新。
- 分时更新: 将更新任务分散到多个帧,或者寻找 GPU 负载较低的“空闲”时机执行,避免造成游戏帧率的突然卡顿。
4. Light Probe 技术的局限性
尽管 Light Probe 非常强大,但它并非完美,其效果与 Lightmap 相比仍有差距。
- 核心短板: 采样密度稀疏。
- Lightmap 可以在一张纹理上存储数百万个采样点的精细光照。
- Light Probe 即使部署几万个,其空间采样密度也远低于 Lightmap,仅为后者的百分之一甚至更低。
- 具体表现:
- 无法产生像 Lightmap 那样 精细、柔和的接触阴影 (Soft Shadow)。
- 难以表现物体间微妙的 色彩溢出 (Color Bleeding) 效果。
结论: Lightmap + Light Probe 的组合是过去十几年中,在性能和效果之间取得绝佳平衡的“黄金搭档”,它通过“烘焙静态 + 探针动态”的思路,巧妙地构建了一个高效且效果不错的混合式 GI 解决方案。
二、 现代渲染的另一基石:PBR 材质系统
解决了光照问题,我们面临第二个核心挑战: 材质 (Material)。这里引出了现代渲染的基石—— 基于物理的渲染 (Physically Based Rendering, PBR)。
1. 核心理论:微平面理论 (Microfacet Theory)
PBR 的理论基础是微平面理论,它提供了一套统一的框架来解释各种材质的光学现象,听起来高深,但思想非常直观。
- 核心假设: 在微观尺度上,所有表面都是由无数个朝向不同的、完美光滑的微小镜面(Microfacets)组成的。
- 宏观表现的来源: 材质的宏观光学属性(如粗糙度)取决于这些微平面法线的统计分布。
- 光滑表面 (Smooth): 微平面的法线高度集中,朝向基本一致。光线被一致地反射,形成清晰的镜面效果。
- 粗糙表面 (Rough): 微平面的法线朝向混乱、分散。光线被射向四面八方,形成模糊、磨砂般的效果。
2. 光与物质的两种交互
当一束光线照射到物体表面时,根据微平面理论,主要发生两种情况:
- 镜面反射 (Specular Reflection): 光线直接从微平面表面被“弹回”。
- 折射/吸收 (Refraction/Absorption): 光线进入物体内部,其后续行为取决于材质类型。
- 金属 (Metals): 内部的自由电子会迅速吸收掉进入的光子。因此,金属没有漫反射颜色,所有颜色都体现在其带色彩的镜面反射上。
- 电介质/非金属 (Dielectrics): 光子进入内部后,会发生多次 散射 (Scattering),最终从一个随机方向射出。这个过程形成了我们观察到的 漫反射 (Diffuse) 颜色。
3. Cook-Torrance BRDF 模型
PBR 材质模型将上述物理现象数学化,其中最经典和常用的是 Cook-Torrance BRDF (双向反射分布函数) 模型,它主要用于描述镜面反射部分。
该模型由三个核心函数相乘构成,通常被简称为 DFG:
f_specular = D * F * G / (4 * (N·L) * (N·V))
-
D - 法线分布函数 (Normal Distribution Function, NDF)
- 作用: 描述微平面法线的统计学分布情况。即,回答“有多少比例的微平面正好朝向某个特定方向?”。
- 关键参数: 粗糙度 (Roughness),在公式中通常表现为
α。α越小,法线分布越集中(表面越光滑);α越大,法线分布越分散(表面越粗糙)。 - 常用模型: GGX (Trowbridge-Reitz) 是当今业界最主流、效果最自然的 NDF 模型。
-
F - 菲涅尔方程 (Fresnel Equation)
- 描述了在不同入射角度下,光线被反射和折射的比例。
-
G - 几何遮蔽函数 (Geometry Function)
- 描述了微平面之间的自遮挡(Shadowing)和自屏蔽(Masking)现象。
总结: PBR 的核心思想是通过微平面理论来统一描述材质,并利用 Cook-Torrance 等数学模型,将 粗糙度 (Roughness) 、 金属度 (Metallic) 等符合物理直觉的参数,转化为最终的光照计算,从而实现更加真实和可信的渲染效果。
深入 PBR 核心:剖析 Cook-Torrance BRDF 的三大组件 (D, G, F)
在现代实时渲染中,基于物理的渲染(PBR)已经成为标准。其核心是 Cook-Torrance 双向反射分布函数 (BRDF),它通过模拟微观表面(Microfacet)的光照交互,实现了极为逼真的材质效果。本次笔记将深入解析构成 Cook-Torrance BRDF 的三大核心组件: 法线分布函数 (D) 、 几何函数 (G) 和 菲涅尔函数 (F)。
一、法线分布函数 (NDF): GGX 的魅力所在
法线分布函数(Normal Distribution Function, NDF)描述了微观层面法线的统计分布情况,它直接决定了高光的形状、大小和锐利程度。在众多 NDF 模型中, GGX (Trowbridge-Reitz) 因其出色的表现力而脱颖而出,成为业界主流。
核心思想:一个“好音箱”的比喻
要直观理解 GGX 为何优于 Phong 等传统模型,可以将其比作一个高品质的音响系统:
- 高音要清脆 (High-frequency Peak): GGX 的高光核心部分非常尖锐和明亮,能够表现出金属或光滑表面上那种“清脆”的亮点。
- 低音要浑厚 (Low-frequency Tail): 与此同时,GGX 的高光衰减非常平缓和宽广,形成一个长长的“拖尾”。这使得高光向周围环境的过渡非常柔和,避免了传统模型中常见的“贴膏药”式的生硬边缘。
这种 “中心尖锐,边缘柔和” 的特性,使得 GGX 能够更真实地模拟现实世界中各种材质的高光反射。
关键参数:Alpha (α)
GGX 模型引入了一个至关重要的参数 Alpha (α),它直接由我们更熟悉的材质属性 Roughness (粗糙度) 计算而来。
- 低 Roughness (α → 0): 微表面法线分布非常集中,材质表面接近镜面,高光小而亮。
- 高 Roughness (α → 1): 微表面法线分布非常离散和随机,材质表面粗糙,高光范围大而模糊。
实时渲染的哲学:“看起来对”就够了
讲座中提到,许多复杂的物理推导在实时渲染中都被大胆地简化和假设了。这正是实时渲染的核心精神: 在性能预算内,只要视觉效果“看起来基本正确”,就可以接受一定程度的近似和“Hack”。GGX 的数学形式虽然看起来复杂,但最终实现的代码却相当简洁高效。
二、几何函数 (G): 微观层面的自遮挡
几何函数(Geometry Function)描述了微观表面上的自遮挡效应。由于表面是凹凸不平的,光线在传播过程中可能会被微观结构自身所遮挡。
核心思想:光线与视线的“双重遮挡”
G 项主要考虑两种遮挡情况:
- Shadowing (阴影): 入射光线在到达某个微表面前,被其他微表面遮挡。
- Masking (遮蔽): 从某个微表面反射出的光线,在到达视线(相机)前,被其他微表面遮挡。
目前业界广泛采用的是 Smith 模型,它将这两种效应结合起来进行计算。
Smith 模型的简化理解
可以这样通俗地理解其工作原理(以各项同性材质为例):
- 假设有 100% 的光能射入材质。根据
Roughness和入射角度,G 函数计算出有 30% 的光被遮挡(Shadowing),剩下 70% 的有效光能参与反射。 - 这 70% 的光能向视线方向反射。由于材质是各项同性的,微观结构是随机均匀分布的,因此视线方向同样会发生遮挡。G 函数再次计算,这 70% 的能量中又有 30% 被遮蔽(Masking)。
- 最终,到达视线的光能是
70% * 70% = 49%。
这个过程确保了能量守恒,粗糙的表面不会反射出比入射光更多的能量。
参数的巧妙复用
Cook-Torrance 模型最精妙的一点在于,计算 G 项的 Smith 模型 同样使用了由 Roughness 推导出的 Alpha (α) 参数。这意味着我们只需要提供一个 Roughness 值,就可以同时控制 NDF (D项) 和几何函数 (G项),极大地简化了材质参数。
三、菲涅尔函数 (F): 掠射角的反射增强
菲涅尔函数(Fresnel Function)描述了一个众所周知的物理现象: 当你的视线以掠射角度(接近平行于表面)观察一个物体时,其反射率会急剧增加。
现实世界的例子
最经典的例子就是观察远处湿漉漉的柏油马路。当你垂直向下看时,路面是深色的;但当你眺望远方时,远处的路面会像镜子一样反射天空和车辆的倒影。这就是菲涅尔效应。
Schlick 近似与“神秘的五次方”
精确计算菲涅尔效应的公式非常复杂。在实时渲染中,我们通常使用一个非常著名且高效的近似公式—— Schlick 近似 (Schlick's Approximation)。
其核心思想是,任何材质的反射率都介于两个值之间:
- F0: 垂直入射(视线垂直于表面)时的基础反射率。这个值可以用来区分金属和非金属。
- 1.0: 掠射入射(视线平行于表面)时的反射率,此时几乎所有材质都接近全反射。
Schlick 近似公式如下:
其中, 是视线方向和法线方向的夹角。这个 5次方 是一个经过大量实验和拟合得出的经验值,它能很好地模拟真实世界中反射率随角度变化的曲线。
四、总结:Cook-Torrance BRDF 的威力
通过将 D (GGX) 、 G (Smith) 、 F (Schlick) 三个组件相乘,Cook-Torrance BRDF 模型就构建完成了。
它的巨大成功在于:
- 物理 plausible: 基于微表面理论,比传统经验模型(如 Blinn-Phong)更符合物理规律和能量守恒。
- 参数直观: 艺术家不再需要调整晦涩的
Power值,而是通过Roughness(粗糙度) 、Metallic(金属度) 和Albedo(基础色) 等直观参数来定义材质。 - 表现力强: 仅用少数几个参数,就能生动地表达出从粗糙的混凝土到光滑的金属等各种截然不同的材质。
五、从理论到实践:测量 BRDF 数据
为了让艺术家能够准确地设置 PBR 参数,图形学界付出了巨大的努力来测量真实世界材质的 BRDF 数据。
- MERL 实验室的贡献: 像 MERL (Mitsubishi Electric Research Laboratories) 这样的机构,使用精密设备(测角反射计)扫描了上百种真实材质,并将其 BRDF 数据公开,形成了著名的 MERL 数据库。
- 对美术师的意义: 这些测量数据为引擎开发者和艺术家提供了宝贵的参考。我们可以知道,真实的木头、塑料、黄金等材质,其
Roughness和F0值大概在什么范围,从而创建出更可信的数字资产。这为 PBR 工作流的标准化和普及奠定了坚实的基础。
PBR 核心理念与工作流:迪士尼原则与 Specular/Glossiness 模型
在这一部分,我们从传统光照模型的局限性出发,深入探讨了现代基于物理渲染(PBR)的指导思想—— 迪士尼 BRDF 原则,并详细解析了业界主流的 PBR 工作流之一: Specular/Glossiness 模型。
一、 从传统模型的困境到 PBR 的曙光
在 PBR 普及之前,即使是像 Cook-Torrance 这样的高级光照模型,在实际生产中也面临着诸多挑战。
传统模型的痛点
- 非直观性: 模型的参数(如高光指数)与物理世界的真实属性关联性不强,艺术家难以直观理解和调节,经常会调出匪夷所思的错误效果。
- 缺乏鲁棒性: 参数组合不当很容易打破物理规律,尤其是能量不守恒。这在包含间接光照(如 Lightmap 烘焙)的场景中是灾难性的,因为能量会在多次反弹中被错误地放大,导致最终画面“过曝”或“炸掉”。
为了解决这些问题,业界需要一套更符合物理规律、同时又对艺术家友好的材质表达方案。迪士尼动画工作室在制作动画电影时,率先系统性地提出了解决方案。
二、 迪士尼 BRDF 原则:PBR 的指导思想
迪士尼的 Brent Burley 提出了一系列关于物理材质设计的信条,这些原则不仅革新了影视动画的渲染,也成为了现代游戏引擎 PBR 体系的基石。其核心理念是: 渲染技术是为艺术家服务的工具,而非纯粹的物理模拟器。
核心理念:为艺术家设计
引擎开发者应将所有物理和数学的复杂性封装在底层,为艺术家和设计师提供一套 直观、简洁、强大且不易出错 的创作工具。我们应该“把困难留给自己,把快乐留给艺术家”。
迪士尼的四大信条
-
参数必须符合艺术家的直觉 (Intuitive Parameters)
- 避免使用抽象的物理学术语(如:吸收光谱频率)。参数应该与艺术家熟悉的视觉概念(如:颜色、粗糙度、金属度)直接挂钩。
-
参数数量应尽可能少 (Minimal Parameters)
- 摒弃过去动辄数十个参数的复杂材质。通过更凝练的设计,用最少的参数覆盖最广泛的材质表现,降低艺术家的学习和使用成本。
-
参数范围应尽可能归一化 (Normalized Range)
- 参数值最好被限制在 0 到 1 的范围内。这比传统模型中无边界的参数(如 Blinn-Phong 的高光指数
power,可以是 10 也可以是 100,但其视觉变化不线性)更易于理解和控制。 - 允许有例外,但超出范围的参数必须能产生有意义且有趣的艺术效果,提供创作弹性。
- 参数值最好被限制在 0 到 1 的范围内。这比传统模型中无边界的参数(如 Blinn-Phong 的高光指数
-
参数组合应具有鲁棒性 (Robust Combinations)
- 无论艺术家如何调整参数,其任意组合都不应产生物理上完全错误或离奇的“坏”结果。每一种组合都应该对应一种在物理上可能存在的、有意义的材质。
三、 主流 PBR 工作流:Specular/Glossiness (SG) 模型
基于迪士尼原则,业界发展出了几种主流的 PBR 工作流。 Specular/Glossiness (SG) 模型 是其中非常经典和完整的一种。
核心思想:用贴图驱动属性
SG 模型最大的特点是,它将材质的各个核心物理属性完全通过贴图来控制,赋予了艺术家像素级别的精确控制能力。几乎不需要手动设置零散的数值参数。
SG 模型的核心贴图 (Inputs)
-
Diffuse Map (漫反射贴图):
- RGB 三通道,定义了材质的基础颜色。在 PBR 语境下,它更常被称为 Albedo。
-
Specular Map (高光贴图):
- RGB 三通道,定义了材质在光线垂直入射时的反射率和反射颜色,即菲涅尔效应中的 F0。
- 使用 RGB 通道至关重要,因为它能准确表达有色金属(如黄金、铜)的反射特性——它们对不同波长的光(R/G/B)反射率是不同的。
-
Glossiness Map (光泽度贴图):
- 单通道灰度图,定义了表面的光滑程度。
- 值越高(越白),表面越光滑,高光反射越清晰;值越低(越黑),表面越粗糙,高光反射越模糊。
- 在 Shader 中,它通常被转换为 Roughness (粗糙度) 使用:
Shader 中的实现逻辑
SG 模型的贴图输入与前面章节提到的 Cook-Torrance 微表面 BRDF 模型 完美结合。
-
获取输入: 从各个贴图中采样得到
Diffuse、Specular (F0)和Glossiness值。 -
计算中间变量: 将
Glossiness转换为Roughness。 -
代入微表面 BRDF 公式:
- 法线分布函数 (D): 主要由
Roughness决定。 - 菲涅尔项 (F): 主要由
Specular (F0)决定。 - 几何遮蔽项 (G): 主要由
Roughness和视线/光线角度决定。
最终的镜面反射光照贡献可以概念性地表示为:
伪代码示意
// 1. 从贴图获取输入 vec3 diffuseColor = texture(diffuseMap, uv).rgb; vec3 specularColor = texture(specularMap, uv).rgb; // F0 float glossiness = texture(glossinessMap, uv).r; // 2. 计算Roughness float roughness = 1.0 - glossiness; // 3. 计算 D, F, G 三项 (使用GGX等具体实现) float D = DistributionGGX(N, H, roughness); float G = GeometrySmith(N, V, L, roughness); vec3 F = FresnelSchlick(H, V, specularColor); // 4. 组合得到最终镜面反射 vec3 specular = (D * G * F) / (4.0 * dot(N, V) * dot(N, L) + 0.001);注意: 在实际编码时,必须严格遵循公式推导中的归一化因子(例如分母中的
4 * dot(N,V) * dot(N,L)或其他常数如π),这些是确保能量守恒的关键,稍有疏忽就可能导致渲染结果在某些角度下看起来是错误的。 - 法线分布函数 (D): 主要由
SG 模型的优缺点
-
优点:
- 功能强大且完整: 能够精确地表达各种材质,无论是金属还是非金属。
- 符合物理直觉: 遵循迪士尼原则,艺术家创作出的材质效果稳定且可预测。
- 像素级控制: 给予艺术家极高的创作自由度。
-
缺点:
- 过于灵活: 特别是
Specular贴图,艺术家需要同时理解并绘制 F0 的颜色和强度,对于区分导体(金属)和绝缘体(非金属)的物理规则需要有一定认知,否则容易出错。这一点也催生了另一种更为主流的工作流。
- 过于灵活: 特别是
高级PBR工作流与Image-Based Lighting
在上一部分我们理解了 PBR 的核心理论基础后,这一部分将深入探讨业界主流的两种 PBR 材质工作流,并引出实现真实环境光照的核心技术——Image-Based Lighting (IBL)。
一、 PBR 材质工作流:从 Specular/Glossiness 到 Metallic/Roughness
PBR 的理论模型虽然统一,但在实践中,为了方便美术师创作并保证物理正确性,业界演化出了两种主流的材质工作流(Workflow)。
1. Specular/Glossiness (SG) 模型的优势与挑战
这是早期也更接近物理原始定义的模型。
- 核心观点: SG 工作流给予了美术师极高的自由度,可以进行像素级的精准控制。例如,可以精确定义高光反射的颜色(Specular)和表面的光滑度(Glossiness)。
- 关键优势: 灵活性极高。理论上可以创造出任何符合物理规律的材质。
- 实践挑战: 过于灵活导致容易出错。尤其体现在
Specular通道,它是一个 RGB 颜色值。如果美术师设置不当(例如,为一个非金属材质设置了彩色的高光),就会轻易地破坏菲涅尔效应(Fresnel),导致 F0(0度角反射率)值不符合物理规律,最终渲染出的材质会显得非常“假”和奇怪。
2. Metallic/Roughness (MR) 模型的诞生与思想
为了解决 SG 工作流的易错问题,工业界提出了一种更为主流、更“防呆”的方案。
- 核心观点: MR 工作流通过引入
Metallic(金属度) 这个参数,巧妙地限制了美术师的创作范围,确保最终材质的物理正确性。它是一种更符合直觉且不易出错的方案。 - 关键术语:
BaseColor(基础颜色): 定义了材质的基础色。Roughness(粗糙度): 与 SG 中的 Glossiness 相反,定义了表面的粗糙程度,值越高表面越粗糙,反射越模糊。Metallic(金属度): 这是一个关键的、通常为 0 到 1 的灰度值,它扮演了一个“开关”的角色,决定了材质是电介质 (Dielectric) 还是 金属 (Metal)。
3. MR 模型的核心机制:对 SG 模型的智能封装
可以把 MR 模型理解为在 SG 核心模型外面包了一层用户友好的“外壳”。
-
核心思想: MR 模型通过
Metallic值自动处理复杂的 F0 计算,避免美术师手动设置错误的参数。- 当
Metallic= 0 (非金属):BaseColor定义了材质的 漫反射颜色 (Diffuse Color)。- 高光反射颜色 (Specular Color / F0) 被锁定在一个很低的固定值(通常是
0.04左右的灰色),符合绝大多数非金属的物理特性。
- 当
Metallic= 1 (金属):- 材质没有漫反射(漫反射颜色为黑色)。
BaseColor被直接用作 高光反射颜色 (Specular Color / F0),这符合金属的物理特性(金属的反射颜色就是它本身的颜色)。
- 当
0 < Metallic < 1:- 系统会在这两种状态之间进行插值(Lerp),平滑地从非金属过渡到金属。
- 当
-
绝佳类比: 这就像一个功能极其强大但操作复杂的专业软件。为了让普通用户也能用好,开发者在外面包了一层“小白模式”,只提供几个简单的开关。用户虽然牺牲了一些自由度,但能确保系统稳定、结果正确。 MR 模型就是 PBR 材质的“小白模式”。
4. 两种工作流的优缺点与业界实践
| 工作流 | 优点 | 缺点 | 业界应用 |
|---|---|---|---|
| Specular/Glossiness (SG) | 灵活性极高,控制精准 | 容易出错,对美术师要求高,易破坏物理规律 | 少数特定流程或引擎仍在使用 |
| Metallic/Roughness (MR) | 符合直觉,不易出错,可控性强 | 自由度略低,在金属与非金属过渡区域可能产生轻微的 白边瑕疵 (White Edge Artifact) | 绝大多数现代游戏引擎(如 Unreal, Unity)和工作室的首选 |
结论: 对于大型团队协作项目,可控性和稳定性至关重要。因此,MR 工作流凭借其鲁棒性成为了当今游戏行业的标准实践。
二、 Image-Based Lighting (IBL):让环境“活”起来
解决了单个材质的渲染问题后,我们如何让物体融入到真实的环境光照中呢?这就是 IBL 要解决的问题。
1. IBL 的核心思想:预计算环境光卷积
- 核心观点: 真实世界的光照来自四面八方,而不仅仅是几个点光源。IBL 技术通过一张 环境贴图 (Environment Map) 来捕捉整个场景的光照信息,并预先计算这张贴图与 BRDF 的光照积分(卷积),从而在运行时以极高的效率实现真实的环境光照效果。
- 关键术语:
Cubemap(立方体贴图): 最常用的环境贴图形式,用六张贴图组成一个立方体,可以采样到来自任何方向的光照信息。- 卷积 (Convolution): 在此可以理解为,对于表面上的某一点,将其 BRDF 函数与来自所有方向的环境光进行积分运算,得到最终的光照结果。
- 空间换时间 (Space-for-Time Tradeoff): 这是图形学中一个经典优化思想。IBL 正是其实践:花费一次性的(离线)计算和一些存储空间(预计算的贴图),来换取运行时(每帧)极快的查询速度。
2. Diffuse IBL:辐照度图 (Irradiance Map)
处理 IBL 的漫反射部分相对简单。
- 核心思想: 对于一个纯漫反射表面,其接收到的光照只与入射光方向和表面法线的夹角(即
cos项)有关。我们可以预先为环境贴图上的每一个点计算它对周围半球所有光线的漫反射贡献总和。 - 实现方式:
- 将原始的环境
Cubemap与一个cos核进行卷积。 - 得到的结果是一张新的、看起来非常模糊的
Cubemap。这张图被称为Irradiance Map(辐照度图)。 - 在运行时,只需要用物体表面的法线方向
N去采样这张Irradiance Map,就能立刻得到该点接收到的所有环境光的漫反射总和。
- 将原始的环境
3. Specular IBL:预滤波环境贴图 (Pre-filtered Environment Map)
处理高光部分则要复杂得多,因为它还和视角 V 以及粗糙度 Roughness 有关。
- 核心思想: 这是一个复杂的积分,直接求解非常困难。业界采用了一种高效的近似解法,其核心是利用了硬件的一个巧妙特性: Mipmap。
- 关键技巧: 用 Mipmap 等级来存储不同粗糙度下的预计算结果。
Mipmap Level 0: 存储的是原始、最清晰的环境贴图,对应Roughness = 0的情况,即完美的镜面反射。Mipmap Level 1, 2, 3...: 随着 Mipmap 等级的增加,贴图会越来越模糊。这些模糊的贴图恰好可以模拟Roughness值逐渐增大时,表面反射越来越模糊的效果。每一级 Mipmap 都代表了一个特定粗糙度下,环境光与高光 BRDF 预积分后的结果。
- 实现方式:
- 离线生成一张包含多个 Mipmap 层级的
Cubemap,每一层都根据对应的Roughness值进行了不同程度的“预滤波”或“预模糊”。 - 在运行时,根据材质的
Roughness值,计算出应该采样的 Mipmap 等级,然后用反射方向R去这张Cubemap的对应 Mipmap 层级进行采样。
- 离线生成一张包含多个 Mipmap 层级的
通过这种方式,IBL 将极其复杂的实时光照积分问题,巧妙地转化为了两次简单的贴图查询(一次查询 Irradiance Map,一次查询 Pre-filtered Environment Map),极大地提升了渲染效率和真实感。
环境光照与动态阴影
在深入探讨了 PBR 的基础理论后,本次我们将聚焦于两个让游戏世界变得栩栩如生的关键技术: 基于图像的光照(Image-Based Lighting, IBL) 中针对高光部分的解决方案,以及在广阔场景中实现动态阴影的主流技术—— 级联阴影贴图(Cascaded Shadow Maps, CSM)。
IBL Specular:让高光在环境中“活”起来
我们知道,PBR 的渲染方程分为漫反射(Diffuse)和镜面反射(Specular)两部分。对于环境光的漫反射部分,我们可以通过预计算的辐照度图(Irradiance Map)来高效求解。但对于镜面反射(高光),情况要复杂得多,因为它与视线方向和材质的 粗糙度(Roughness) 紧密相关。IBL Specular 的核心目标就是高效地模拟这种效果。
核心思想:预计算与近似
IBL Specular 并非实时积分求解,而是采用了一系列巧妙的 预计算(Pre-computation) 和 近似(Approximation) 方法,将复杂的计算结果存储在贴图中,运行时只需进行简单的采样。这套方案主要包含两个关键部分:
1. 预过滤环境贴图 (Pre-Filtered Environment Map)
这个技术巧妙地利用了硬件特性 Mipmap 来存储不同粗糙度下的环境反射结果。
- 核心观点: 将材质的 粗糙度(Roughness) 与 CubeMap 的 Mipmap 层级 进行映射。
- 实现原理:
- Roughness = 0 (完全光滑): 对应 Mipmap 的最高层(Level 0),即原始的、最清晰的环境贴图,用于实现镜面反射。
- Roughness > 0 (逐渐粗糙): 随着粗糙度增加,高光反射会变得越来越模糊。这种模糊效果在视觉上等同于低频信息。因此,可以将不同粗糙度等级下预过滤(模糊)过的环境贴图,依次存入 Mipmap 的更低层级(Level 1, 2, 3...)。
- 优势: 运行时,我们可以根据物体表面的粗糙度值,计算出需要采样的 Mipmap 层级,从而用一次三维纹理采样(
texCUBElod)就获取到对应模糊程度的环境反射,效率极高。
- 重要提示: 这里的 Mipmap 不是通过硬件自动生成的,而是需要我们离线为每一层单独计算并填充的。每一层都代表一个特定的粗糙度等级下的预积分结果。
2. 双变量 BRDF (BRDF Look-up Table)
除了环境贴图,BRDF 方程本身也有一部分可以被预计算出来,以加速菲涅尔效应(Fresnel)等部分的计算。这就是所谓的 查找表(Look-up Table, LUT)。
- 核心观点: 将 BRDF 方程中与视线角和粗糙度相关的部分预计算成一张 2D 纹理(LUT)。
- 实现原理:
- 这张 2D LUT 通常有两个输入维度:
- 表面粗糙度 (Roughness)
- 视线与法线的夹角余弦值 ()
- 纹理中存储的通常是两个值:一个 缩放(Scale) 和一个 偏移(Bias)。在运行时采样这张 LUT,得到的这两个值可以用来近似计算菲涅尔项,使得原本复杂的 Cook-Torrance BRDF 在环境光下的镜面反射部分变得近似线性,极大简化了计算。
- 这张 2D LUT 通常有两个输入维度:
IBL 的价值
结合以上两点,IBL Specular 方案虽然是基于大量假设的近似解,但它带来了革命性的视觉提升:
- 真实的高光: 首次让游戏场景中的物体能够从环境中反射出柔和、模糊且带有环境色彩的高光,而不仅仅是点光源产生的生硬光斑。
- 丰富的层次感: 如下图对比所示,加入 IBL 后,场景的材质质感和空间层次感都得到了极大的增强,整体视觉效果更舒适、更真实。
- 行业标准: 正是由于其出色的效果和高效的性能,IBL 与 PBR 相辅相成,迅速成为过去十几年所有 3A 游戏引擎的标配技术。
动态阴影的主流方案:Cascaded Shadow Maps (CSM)
在广阔的开放世界游戏中,如何高效地渲染从近到远都清晰可见的动态阴影,是一个巨大的挑战。 级联阴影贴图(Cascaded Shadow Maps, CSM) 正是为了解决这个问题而诞生的经典方案。
核心问题:分辨率的权衡
传统的阴影贴图(Shadow Map)技术,是将整个场景从光源视角渲染到一张深度图上。但在大场景中,这会遇到一个不可调和的矛盾:
- 高分辨率 Shadow Map: 可以保证近处阴影清晰,但覆盖范围有限,且性能和显存开销巨大。
- 低分辨率 Shadow Map: 可以覆盖广阔的远景,但会导致近处物体的阴影出现严重的锯齿和失真("像素块")。
你无法用一张固定精度的 Shadow Map 同时满足近处枪械的精细阴影和远处山脉的轮廓阴影。
CSM 的解决方案:分而治之
CSM 的思想非常直观且有效,就像它的名字“级联”(或“瀑布”)一样,它将问题分解处理。
- 核心观点: 将摄像机的 视锥体(View Frustum) 沿深度方向分割成若干个层级(Cascades/Splits)。
- 实现原理:
- 视锥体分割: 将摄像机能看到的空间,从近到远切分成几块区域。例如:0-10米,10-30米,30-100米,100-500米。
- 独立 Shadow Map: 为每一个分割出的子视锥体(Cascade)生成一张独立的、大小相同的 Shadow Map。
- 分辨率的重新分配:
- 近处 Cascade: 用一张高分辨率的 Shadow Map 覆盖一小片区域,保证了近景阴影的极高质量。
- 远处 Cascade: 用同样分辨率的 Shadow Map 覆盖一大片区域,虽然单位面积的精度下降了,但由于透视效应(近大远小),远处的阴影在屏幕上本身就占据较少像素,这种精度已经足够。
- 渲染时采样: 在为屏幕上的某个像素着色时,首先判断该像素所代表的物体点位于哪个 Cascade 区域,然后采样对应的 Shadow Map 来计算阴影。
CSM 的挑战与代价
这个看似淳朴的想法虽然统治了游戏行业十几年,但在实践中也面临着巨大的挑战。
- 层级间的混合 (Blending): 如果不进行处理,不同 Cascade 的交界处会因为分辨率的突变而产生一条非常明显的硬边界。实际项目中需要使用各种滤波和混合技术(通常是一些非常巧妙的 "dirty hacks")来平滑过渡,消除这条接缝。
- 性能开销 (Performance Cost): CSM 是一个非常昂贵的渲染过程。
- 绘制调用 (Draw Calls): 场景需要从光源视角被重复绘制多次(每个 Cascade 绘制一次)。
- 显存占用: 需要存储多张 Shadow Map,增加了显存压力。
- CPU 开销: 需要为每个 Cascade 单独进行视锥体裁剪和可见性计算。
- 在复杂的 3A 游戏中,阴影渲染的耗时通常在 2ms 到 5ms 之间,是渲染管线中最耗时的模块之一。
软阴影技术简介
为了让阴影边缘更加柔和自然,业界发展出了多种软阴影技术,其中最经典的两个是:
- PCF (Percentage-Closer Filtering): 这是软阴影的基础。它不再是只采样 Shadow Map 的一个点,而是在该点周围的一个小区域内进行多次采样,并计算采样点中处于非阴影状态的比例,从而得到一个平滑的阴影边缘。
- PCSS (Percentage-Closer Soft Shadows): PCF 的一个高级变种。它能模拟出更真实的 半影(Penumbra) 效果,即阴影会随着遮挡物与接收物距离的增加而变得更加模糊。PCSS 通过动态计算PCF的滤波范围来实现这一点,是目前许多引擎中标配的高质量软阴影方案。
从经典阴影技术到次世代实时渲染
一、 高级软阴影技术回顾
在上一部分 Shadow Mapping 的基础上,讲座深入探讨了两种在工业界广泛应用的、用于实现软阴影的高级技术。
1. PCSS (Percentage-Closer Soft Shadows)
- 核心观点: PCSS 是对基础的 PCF (Percentage-Closer Filtering) 的一种精妙改进。它不仅仅是简单地在阴影边缘进行滤波,而是 模拟了真实的半影(Penumbra)效果。
- 关键原理: PCSS 的核心思想是让阴影的柔和程度与遮挡物和接收物之间的距离相关联。
- 首先,通过一次采样(Sample 0)来估算遮挡物(Blocker)的平均深度。
- 然后,根据这个平均深度以及光源的大小,计算出合适的滤波范围(Penumbra Size)。
- 最后,在这个动态计算出的范围内进行 PCF 滤波。
- 业界地位: PCSS 是一种非常成熟且效果出色的技术,在许多现代游戏引擎中都是软阴影的标配方案,能有效缓解阴影的锯齿(Aliasing)问题。
2. VSM (Variance Soft Shadow Maps)
- 核心观点: VSM 是一种基于统计学思想的软阴影技术,它通过存储深度的均值和方差来快速估算阴影的遮蔽百分比,从而实现非常高效的模糊效果。
- 关键原理:
- 在生成 Shadow Map 时,我们不仅存储深度值 (一阶矩,即均值 ),还存储深度的平方 (二阶矩 )。
- 通过这两个值,我们可以轻松计算出某个区域内深度分布的 方差 (Variance):
- 在着色时,利用 切比雪夫不等式 (Chebyshev's inequality),可以根据当前片元的深度和查询区域的均值、方差,快速估算出该片元被遮挡的概率上限。
- 评价: 尽管 VSM 的数学推导在某些情况下并不完全精确(被讲者称为“hacks”),但它在实践中效果极佳且性能很高,因此也成为了许多引擎中的常用选项。
二、 上一代渲染技术的“黄金组合”
讲座总结了大约 5-10 年前,构建一个 3A 级游戏渲染引擎所需的核心技术栈。掌握这些技术,就基本具备了开发商业级渲染引擎的能力。
-
全局光照 (Global Illumination):
- 静态光照: Lightmap (光照贴图)
- 动态物体/角色: Light Probe (光照探针)
- 这是一个解决不同场景光照需求的经典组合。
-
材质 (Material):
- PBR (Physically Based Rendering): 毫无疑问的业界标准,一统江湖。开发者需要熟练掌握其两大主流工作流: Specular/Glossiness 和 Metallic/Roughness。
-
环境光 (Ambient Lighting):
- IBL (Image-Based Lighting): 基于图像的光照,是实现高质量环境光和反射的基石,与 PBR 材质模型完美契合。
-
阴影 (Shadow):
- CSM (Cascaded Shadow Maps): 解决大规模场景下动态阴影分辨率问题的关键。
- 软阴影 (Soft Shadow): 结合 PCSS 或 VSM 等技术,提升阴影的真实感。
三、 新时代的来临:硬件革命与渲染管线的颠覆
近些年,渲染技术正经历一场剧烈的变革,其根本驱动力源于硬件和图形 API 的飞速发展。
-
硬件驱动力:
- GPU 算力 的爆炸式增长。
- 图形 API 的进化: DirectX 12, Vulkan 等现代 API 提供了更底层的硬件控制能力。
-
带来的核心变革:
- 通用计算的解放: 强大的 计算着色器 (Compute Shader) 让 GPU 不再局限于传统的图形渲染管线,使得过去许多“想做不敢做”的复杂算法成为可能。
- 高效的数据通信与同步: 在 GPU 内部进行数据的高效流转和处理变得更加便捷。
结论: 这场硬件革命正在彻底颠覆传统的渲染底层算法和逻辑,催生了大量前所未有的新技术和新方法。
四、 次世代渲染前沿技术概览
1. 实时光线追踪 (Real-Time Ray Tracing)
- 核心能力: 现代 GPU (如 NVIDIA RTX 系列) 提供了硬件加速的光线与场景求交功能。开发者只需定义光线,硬件就能高效地返回与场景(通常通过 BVH - Bounding Volume Hierarchy 加速结构组织)的相交结果。
- 当前主流应用: 实时反射 (Real-time Reflections)。这是光追技术最直观、效果最显著的应用之一,已成为许多现代游戏的标配特性。
- 未来潜力: 光线追踪的真正潜力远不止于反射,它将 彻底改变实时全局光照 (Real-Time GI) 的实现方式,是通往更高画质的钥匙。
2. 实时全局光照 (Real-Time GI): 下一个战场
Real-Time GI 是当前图形学领域最活跃、发展最快的方向之一,也是衡量一个商业引擎是否达到“次世代”标准的重要指标。
-
标杆案例: Unreal Engine 5 的 Lumen 系统。它并非单一算法,而是一个极其复杂的混合系统,融合了多种 GI 技术(如 Screen Space GI, SDF Tracing, Voxel GI 等)来应对不同距离和复杂度的场景,最终实现了惊艳的动态全局光照效果。
-
业界涌现的多种 GI 技术:
- Screen Space GI (SSGI): 在屏幕空间进行,速度快但有局限性。
- SDF (Signed Distance Fields) based GI: 基于有向距离场进行光线步进。
- Voxel based GI: 将场景体素化,代表技术有 SVOGI (Sparse Voxel Octree GI) 和 VXGI (Voxel Global Illumination)。
- Reflective Shadow Maps (RSM): Shadow Map 的一种扩展,用于收集间接光。
- RTXGI: 利用硬件光追实现的 GI 方案。
给开发者的启示: 这是一个蓬勃发展的领域,充满了机遇和挑战。密切关注该领域的前沿论文和技术分享,对于渲染工程师的成长至关重要。
3. 其他前沿领域:复杂材质渲染
强大的算力也使得过去非常昂贵的材质渲染技术得以在实时环境中使用。
- 皮肤渲染: SSS (Subsurface Scattering) 材质可以更精确地模拟光线在皮肤内部的散射效果,让角色看起来更加生动逼真。
- 毛发渲染: 借助 Geometry Shader 等技术可以动态生成海量发丝细节,并应用复杂的光照模型,实现极其细腻和真实的毛发效果。
高级渲染技术与工程实践
在这一部分,讲座的核心内容从具体的渲染技术(如阴影)过渡到了现代游戏引擎开发中更为宏观和工程化的挑战: 着色器(Shader)的规模化管理 与跨平台兼容性。
一、 现代渲染技术趋势:算力驱动的真实感
讲座首先简要提及了现代GPU强大的算力如何推动渲染技术的发展,使得过去难以实现的效果变得可能。
- 核心观点: 强大的并行计算能力是实现复杂物理模拟效果的基石。
- 关键案例: 次表面散射 (Subsurface Scattering, SSS)。通过强大的算力,我们可以实时模拟光线在玉石、皮肤等半透明材质内部散射的复杂物理过程,从而极大地提升了真实感。
二、 高级阴影技术:虚拟阴影贴图 (Virtual Shadow Maps)
在阴影技术方面,讲座特别强调了一个区别于传统 级联阴影贴图 (Cascaded Shadow Maps, CSM) 的前沿方向。
-
核心观点: 虚拟阴影贴图 (Virtual Shadow Map, VSM) 是解决大规模场景下动态阴影渲染难题的一个极具潜力的方案,尤其是在处理精度和性能开销的平衡上。
-
灵感来源: 这一思想借鉴了图形学大神 John Carmack 提出的 虚拟纹理 (Virtual Texture) 概念。虚拟纹理将整个游戏世界的所有纹理映射到一张巨大的虚拟纹理上,并根据视点需要动态地加载和卸载(streaming)纹理块。
-
VSM 工作原理:
- 虚拟化: 想象存在一张覆盖整个场景的、巨大无比的虚拟Shadow Map。
- 按需分配: 引擎算法会分析场景,判断哪些区域需要生成阴影、需要的精度(密度)是多少。
- 动态分配空间: 根据分析结果,在巨大的虚拟Shadow Map上为这些区域动态地分配存储空间。
- 分块生成 (Tiled Generation): 将需要计算的阴影区域分割成一小块一小块的图块(Tile),并独立生成它们的Shadow Map。
- 采样: 当渲染场景中的物体时,根据其位置和需要,反向查询并采样虚拟Shadow Map上对应的图块。
-
VSM 的优势:
- 高空间利用率: 相比于CSM固定划分且可能存在浪费的“级联”,VSM只为实际需要的区域分配资源,空间利用率更高。
- 灵活性与高精度: 可以为近处的物体分配高分辨率的阴影图块,为远处的物体分配低分辨率的图块,实现了精细化的按需精度控制。
-
实践建议: 对于正在开发或研究现代渲染引擎的工程师来说, VSM是一个非常值得关注和投入研究的新方向。虚幻引擎5(Unreal Engine 5)的实践已经证明了其有效性。
三、 引擎工程实践:应对“着色器爆炸”
现代游戏引擎面临的一个巨大工程挑战是管理数量庞大的着色器。
-
核心观点: 随着渲染功能和材质复杂度的提升,着色器的组合数量会呈指数级增长,形成所谓的“着色器爆炸”(Shader Explosion),必须采用系统化的方法进行管理。
-
“着色器爆炸”的两个主要来源:
- 艺术家驱动: 艺术家通过 着色器图 (Shader Graph) 等可视化工具可以自由创作出成千上万种材质效果,每一种都对应一个或多个着色器。
- 程序员驱动: 渲染工程师为了应对不同的渲染路径和功能组合,会定义大量的编译选项。例如:
- 光源类型 (点光源, 面光源, GI, SH等)
- 材质属性 (单面/双面渲染, Alpha测试/混合)
- 渲染管线状态 (正向渲染, 延迟渲染)
- ...等等
-
解决方案:Ubershader 与着色器变体 (Shader Variants)
- 关键术语: Ubershader
- 核心思想: 编写一个功能全面、包含所有可能性的“超级着色器”模板。在这个模板内部,使用 宏定义 (Preprocessor Macros) (如
#ifdef,#if)来包裹不同的功能代码块。 - 编译过程: 编译器会根据不同的宏定义组合,从这个Ubershader模板中编译生成出成千上万个具体、优化后的着色器版本。这些版本被称为 着色器变体 (Shader Variants) 或 排列组合 (Permutations)。
- 实例: 讲座中提到,某引擎通过 165个 Ubershader 模板,最终生成了 超过 70,000 个 实际使用的着色器变体。
- Ubershader的优势:
- 可维护性: 当需要修改某个光照算法或修复一个通用Bug时,只需修改Ubershader模板中的一处代码,所有相关的变体就能自动重新编译并更新,极大地降低了维护成本和出错风险。
- 性能: 预先编译所有变体,避免了在GPU上执行时使用动态分支(
if-else)。GPU极不擅长处理分支,因为会导致线程束(warp/wavefront)中的线程执行路径不一,造成效率下降。将分支在编译期展开为不同的变体,可以保证每个变体在运行时都是线性、无分支的,从而最大化GPU执行效率。
四、 引擎工程实践:跨平台着色器编译
着色器语言的碎片化是跨平台引擎开发的另一个痛点。
-
面临的挑战: 不同图形API和平台使用不同的着色器语言。
- DirectX: HLSL (High-Level Shading Language)
- OpenGL: GLSL (OpenGL Shading Language)
- Apple Metal: MSL (Metal Shading Language)
- PlayStation: PSSL
- ...等等
-
现代解决方案: SPIR-V (Standard Portable Intermediate Representation)
- 核心观点: 使用一个标准的、可移植的 中间语言 (Intermediate Representation, IR) 作为桥梁,实现“一次编写,到处运行”的着色器管线。
- 工作流程:
- 编写: 使用一种主流高级语言(如HLSL或GLSL)编写Ubershader。
- 编译到IR: 将高级语言代码编译成平台无关的 SPIR-V 字节码。
- 交叉编译 (Cross-Compile): 使用如
SPIRV-Cross等开源工具,将SPIR-V字节码再翻译成目标平台所需的原生着色器代码(如MSL, HLSL, GLSL等)。
- 实践建议: 在引擎设计初期就应考虑跨平台编译方案。 优先将着色器编译到Vulkan所使用的SPIR-V版本,再由此转换到其他平台,可以有效避免为每个平台维护一套独立着色器代码的噩梦,极大简化开发和调试流程。
Q&A
本次课程是渲染部分的收尾,内容以问答 (Q&A) 的形式展开,探讨了图形学领域的一些前沿问题和未来发展方向,并给出了后续的学习建议。
一、 技术问答与前沿探讨 (Q&A)
1. 全局光照 (GI) 的未来发展趋势
- 核心观点: 随着硬件性能的飞速发展, GI (全局光照) 问题有望在未来5年左右被彻底解决,并成为未来游戏引擎的标配功能。
- 技术展望: 讲师个人非常推崇 Photon Map 算法,并认为这类曾经的离线算法正逐步具备在游戏引擎中实时化的潜力。这预示着学术界和工业界正在积极探索将更高质量的GI算法引入实时渲染。
- 战略意义: 对于着眼于未来10年的引擎开发者而言,GI是一个必须攻关和持续跟进的前沿方向。
2. 云渲染能否解决 GI 的性能瓶颈?
- 核心观点: 云渲染,特别是 端云协同 (Client-Cloud Synergy) 的模式,有潜力解决GI的性能瓶颈。
- 基本原理: 渲染方程中的计算可以分解为 视点相关 (view-dependent) 和 视点无关 (view-independent) 两部分。
- 视点相关: 计算结果随玩家摄像机位置和方向改变,必须在客户端实时计算(如高光反射)。
- 视点无关: 计算结果在场景中是固定的,不随观察者改变(如光照贴图的烘焙、体素数据的构建)。
- 应用场景: 像 SBVGI (Sparse Voxel-based Global Illumination) 这类数据结构的构建是视点无关的。这类计算可以在云端统一完成一次,然后分发给大量用户。这种模式极大地摊薄了单次计算的高昂成本,使得高质量的全局光照在多人场景中变得可行。
3. 如何实现游戏中的动态日夜循环?
- 核心观点: 游戏中的动态日夜系统 (常被称为 TOD - Time of Day) 是一个复杂系统,它不仅是光源的变化,更涉及到与 天空渲染 (Sky Rendering) 的紧密耦合。
- 关键挑战 1: 巨大的光照动态范围
- 正午阳光与月光的亮度差异可达数万倍以上。
- 这要求渲染管线必须基于物理,能够正确处理如此宽广的亮度范围,这也是 PBR Light 的核心理念之一。只有输入物理准确的光照参数,才能获得真实的光照表现。
- 关键挑战 2: 环境光的重要性 (IBL)
- 天空本身是一个重要的面光源。在白天,环境光(天光)的贡献能占到总光照的约五分之一,在阴影区域尤其关键。
- 因此,TOD系统必须准确模拟天光在一天中颜色和强度的变化。
- 关键挑战 3: 真实感模拟
- 为了达到高真实感,系统需要模拟不同纬度、气候下的光照和大气效果,这需要深入的物理知识和复杂的着色器实现。
二、 学习建议与课程后续安排
- 学习重点: 建议熟悉课程使用的小引擎框架。
- 核心区别: 学习引擎与学习算法存在显著不同。
- 学习算法: 理解原理后,可以在一个简单的框架(如单个
main.cpp)中快速实现和验证。 - 学习引擎: 首要任务是 理解代码架构,找到插入和修改代码的正确位置。不熟悉引擎框架,即使理解了算法原理也无从下手。因此,花时间阅读和理解引擎代码是至关重要的一步。
- 学习算法: 理解原理后,可以在一个简单的框架(如单个