
做渲染这几年我经常碰到一个尴尬场面跟做网络的同事聊技术我一提“PBR”Physical Based Rendering对方马上接话“策略路由啊我们在核心交换机上也配了PBR。”两个人各说各话聊了半天才发现讲的根本不是一回事。其实这个缩写撞车挺有意思——一边是图形学里把光照算得越来越“真实”的渲染方案另一边是网络里根据策略而不是目的地址选路的路由机制。今天这篇要聊的是渲染圈的PBR也就是基于物理的渲染Physical Based Rendering。它解决的是一整套“怎么让画面看起来可信”的问题金属就是金属塑料就是塑料皮肤在逆光下不该死黑车漆在傍晚不该糊成一团。这篇文章适合TA、3D美术、图形程序员以及所有被“PBR”这个术语困住过的人——我会把原理、贴图逻辑、环境光照、引擎落地和排错经验一次讲透。1. 先厘清PBR 的两个身份以及为什么渲染圈都在用它很多刚入行的人看到“PBR”三个字母第一反应是去搜索引擎查结果一半结果是策略路由另一半是渲染越查越乱。我干脆先把这事说清楚后面就不再纠结了。1.1 网络里的 PBR 策略路由网络领域的 PBR 全称是 Policy Based Routing中文叫策略路由。传统路由是看目的IP决定下一跳策略路由则是管理员自定义一套策略比如来自某个网段的流量走某条链路某种应用优先级更高或者按源地址、端口、报文长度去分流。它解决的是“灵活调度流量”的问题和你做模型、调材质、调光照没有半点关系。一个搞渲染的人如果拿图形学的 PBR 文章去理解网络配置那基本等于拿着一本菜谱去修发动机完全不搭。1.2 图形学里的 PBR一套让材质表现趋于真实的标准渲染圈的 PBR 全称是 Physical Based Rendering基于物理的渲染。它的核心出发点不是“怎么画好看”而是“怎么算得对”。老一代的光照模型Phong、Blinn-Phong主要靠经验参数去“凑”出高光看着像就行PBR 则基于真实世界的光学规律去建模——微表面反射、能量守恒、菲涅尔现象——让材质在不同光照、不同角度下都保持合理的表现。到2025年PBR 已经不只是游戏引擎的标配。glTF 2.0 这种 3D 资产格式把 PBR 材质作为标准材质模型Substance Painter、Blender、Marmoset Toolbag 这些工具输出的默认工作流就是 PBR连影视离线渲染里也大量采用类似的物理光照思路。可以说只要你想让自己的模型在任意软件、任意引擎里看起来一致、真实PBR 就绕不过去。2. 为什么传统光照算法绕不开“能量不守恒”这个坎要说清楚 PBR 的价值得先回头看传统光照模型的问题。很多人第一次用 PBR 材质时感觉“无非就是加了几张贴图”其实真正的变革在光照计算层面。2.1 Blinn-Phong 模型的直觉缺陷Blinn-Phong 是很多图形学入门课第一个讲的光照模型公式不复杂环境光加漫反射加高光高光用一个指数控制光斑大小。它的问题在于这几个分量是独立算完直接相加的没人管加完之后能量是否超过入射光。举个例子一个表面同时有很强的漫反射贴图和高光指数当光源从某个角度照过来时反射出去的能量可能比接收到的还多——这在物理上不可能但在画面里体现为“过曝”“发灰”“死白”。另一个问题是高光形状完全靠经验调表面粗糙度与高光大小的对应关系是牵强的同一个材质换个灯光角度真实感就崩了。2.2 能量不守恒在画面里的具体表现材质在不同光照下表现不稳定白天看着还行晚上一盏射灯一打高光就炸。金属和非金属的区分靠贴图颜色硬凑导致金属看起来像“刷了金漆的塑料”。物体在阴影里时暗部信息丢失因为环境光只是一个常量无法反映周围环境。我当年第一次用 PBR 替换掉项目里的 Blinn-Phong 材质时没有改任何美术设计只是把参数重新映射到粗糙度和金属度效果立刻不一样了金属轮毂在黄昏下有了正确的高光收敛塑料内饰也不再到处反光。这就是“能量守恒”在视觉上的威力——它不是让你更亮而是让你更合理。2.3 白炉测试验证能量守恒最简单的方法渲染圈经常说“白炉测试”White Furnace Test做法很简单把一个纯白的、完全平滑的球放进一个纯白的、自带均匀照明的环境里。如果渲染结果是纯白RGB 都是 1或者接近 1说明能量守恒没问题如果变灰或者过曝说明你在某些环节丢了或者多算了能量。这个测试在选引擎、调 BRDF 或排查异常材质时非常好用稍后讲落地问题还会用到。3. 微表面模型与 Cook-Torrance BRDFPBR 的物理地基PBR 最核心的数学工具是 BRDFBidirectional Reflectance Distribution Function双向反射分布函数它描述了光从某个方向入射后向某个方向反射的比例。传统模型也有 BRDF但 PBR 用的 Cook-Torrance 模型是基于微表面理论的物理基础扎实得多。3.1 微表面理论是什么真实物体表面在微观尺度上根本不是平的而是由无数朝向各异的小“微平面”组成。有的微平面朝向光源有的朝向视线粗糙度越高微平面朝向越乱粗糙度越低微平面越整齐。镜面之所以亮是因为所有微平面几乎平行光线定向反射磨砂表面之所以糊是因为微平面朝向混乱光线被打散到各个方向。PBR 里的粗糙度Roughness贴图描述的就是这种微平面朝向的统计规律而不是“表面有多脏”。这个理解特别重要我见过不少美术把粗糙度当“污渍贴图”用结果在光照下一塌糊涂。3.2 Cook-Torrance BRDF 的三个关键项Cook-Torrance 模型可以通俗地拆成三部分D 项法线分布函数NDF描述微平面中朝向视线与光源中间方向的占比。主流用 GGXTrowbridge-Reitz分布它的特点是高光有长尾——高光中心亮边缘衰减不像老模型那样一刀切这让金属和车漆的质感特别真实。G 项几何遮蔽项描述微平面之间的互相遮挡。粗糙度越高微平面越容易互相挡住光线导致边缘变暗。没有 G 项粗糙表面的边缘会发光看起来像镀了一层光晕。F 项菲涅尔项描述光线以不同角度入射时反射率的变化。入射角越接近掠射角即视线越平反射越强。所有表面在掠射角都会变成“镜子”哪怕是一块石头。三者的通用组合形式可以写成一个简短公式只看结构就行f D * G * F / (4 * dot(N, L) * dot(N, V))分母里的点积是几何衰减修正你不用手算引擎都算好了。你只需要知道这三分量共同决定了高光的形状、强弱和边缘渐变。3.3 金属度与菲涅尔为什么金属和塑料看起来不一样菲涅尔公式里有个关键参数 F0表示光线垂直入射时的反射率。真实世界里非金属电介质的垂直反射率很低大概在 0.04 附近所以塑料、皮肤、木头在正对视线时只有轻微高光而金属导体的垂直反射率很高且反射光带上了金属本身的颜色。PBR 的 metallic-roughness 工作流把这个物理事实映射成两个参数金属度Metallic决定材质是导体还是电介质。金属度越高F0 越接近基础色漫反射占比越低。基础色Base Color在非金属区域是漫反射颜色在金属区域则是反射光的颜色相当于 F0。一个很实用的映射公式是F0 lerp(0.04, baseColor, metallic)也就是非金属的 F0 固定在 0.04金属的 F0 直接用基础色。这解释了为什么 PBR 里金属材质的高光往往带颜色而塑料的高光是纯白偏灰的。3.4 能量守恒如何在这套模型里落地PBR 里漫反射和高光是按比例分配的不是各算各的。粗糙度高的金属高光扩散、变弱光滑的塑料高光集中但漫反射仍然存在。最关键的一条金属的漫反射为 0——光打到金属表面要不被反射要不被吸收变成热量不会进入内部再散射出来。这也是为什么金属材质如果用传统模型来调永远调不出那种“清透的金属感”。4. metallic-roughness 工作流每张贴图都不是玄学原理讲完进入美术和 TA 每天都要面对的部分贴图。PBR 资产的常规贴图组包括基础色Base Color/Albedo、法线Normal、粗糙度Roughness、金属度Metallic、环境光遮蔽AO有时还有高度Height贴图。每张贴图的含义和绘制原则都不一样。4.1 Base Color 画纯反照率不要画光影Base Color 表示表面本身的颜色是“没有光照信息”时的反照率。很多新手会犯一个毛病在基础色里画上阴影、高光、甚至 AO。这在 PBR 流程里是坏习惯会导致光照计算时颜色被重复叠加画面又脏又灰。正确做法Base Color 里只体现材质本来的颜色变化比如木头纹理的深浅、金属上的锈斑。光影交给光照系统去算。记住一个口诀“贴图里不存在虚拟光源。”4.2 Roughness 与 Metallic 通道的取值习惯粗糙度通道是灰度图白色1代表完全粗糙黑色0代表完全光滑。取值时不要走极端尤其是 0 和 1 两端现实中几乎没有绝对光滑或绝对粗糙的表面。我的习惯是拉丝金属给 0.4 到 0.6塑料 0.3 到 0.5镜面给 0.05 左右但会配合反射探针模糊度去调而不是直接贴 0。金属度通道同样建议只用 0 或 1 两个极端。PBR 公式里中间值比如 0.5物理上不合理渲染时会出现“既不像金属又不像塑料”的尴尬状态。如果你需要过渡区比如磨损边缘也尽量通过噪声贴图在高频处从 0 跳到 1而不是做平滑渐变。4.3 法线、AO、Height 贴图的角色边界法线贴图改变的是微表面的朝向分布它影响的是高光和反射的细节形状。法线贴图不能替代 Base Color 里的纹理两者是不同维度。AO环境光遮蔽负责模拟微缝隙、角落里的环境光被遮挡它只影响环境光部分不直接影响直接光高光。这个属性决定了 AO 贴图不应该叠加到自己画的“阴影”里。Height 贴图配合视差映射可以做凸起偏移但从视觉矫正角度看它不是必需的。移动端项目可以直接忽略 Height节省采样开销。4.4 两种工作流怎么选metallic-roughness vs specular-glossiness早期还有一套 specular-glossiness 工作流用高光色Specular和光泽度Glossiness两张贴图替代金属度。两者各有拥趸我把对比列一下对比项Metallic-RoughnessSpecular-Glossiness贴图数量Base Color Metallic Roughness 三张Diffuse Specular Glossiness 三张非金属 F0 控制固定 0.04不可微调可通过 Specular 贴图微调金属表现物理准确金属自动有色高光需要手动配置调错容易发灰业界支持glTF、Unreal、Unity、Substance 默认部分老工具和影视流程还在用新手友好度高参数少逻辑清晰低需要理解 specular 的物理意义我的建议是新项目直接选 metallic-roughness工业标准基本都倒向这一边。除非你是在维护老项目受美术资产限制否则没必要绕回 spec-gloss 那一套。5. IBL 环境光照与 split-sum 近似让真实感翻倍的幕后推手很多人把 PBR 理解成“换了一个 Shader”结果换了之后发现效果并不惊艳原因往往是环境光照没跟上。PBR 的真实感有 70% 来自环境光而不是那几盏直接光。5.1 为什么环境光在 PBR 里比直接光还重要在真实世界里几乎没有东西是被单一光源照亮的。天空、墙壁、地面、金属互相反射的光构成了复杂的环境光照。传统渲染默认环境光是常量所以物体暗部是死的PBR 通过 IBLImage-Based Lighting基于图像的光照把环境贴图作为光照来源暗部会反射周围环境金属和光滑表面会映出周围场景。这也是为什么你在引擎里放一个纯金属球它能“拍”出周围的环境。5.2 split-sum 近似的两个缓存实时渲染里不可能对每像素采样整张环境贴图所以业界几乎都用 split-sum 近似把 IBL 拆成两个可预计算的步骤第一项把环境贴图按不同粗糙度做预滤波生成一系列模糊程度不同的 mip 层级。粗糙度 0 用原始贴图粗糙度 1 用极模糊版本。第二项预积分一张 BRDF LUT 查找表用来修正菲涅尔和几何项随角度变化的衰减。实际运行时根据材质 roughness 选择对应 mip 层级采样乘上 BRDF LUT 的查表结果就得到了近似的环境反射。现代引擎Unity、Unreal、Godot都内置了这套方案。你作为使用者不需要自己写 Shader但理解它有助于你判断为什么反射探针的“模糊度”要和 roughness 对应为什么环境贴图分辨率不能太低。5.3 反射探针的选择与摆放经验离线生成的环境贴图比如 HDRI 背景覆盖面大但不精确场景里复杂的局部反射还得靠反射探针。我的实践建议是先用 1 到 2 个“场景级探针”覆盖整体环境保证天空色和主色调正确。在金属物体集中、反射特征明显的区域放局部探针例如洗手间的不锈钢龙头、展厅里的车。探针更新频率按需调整静态场景烘焙后就不需要实时更新动态物体多的场景探针更新每周期间隔可以放到 0.5 秒以上肉眼几乎看不出区别。踩过的一个坑是探针之间过渡生硬。多探针场景里插值权重如果不调物体从一个探针范围走到另一个范围时反射会“啪”地跳变。需要调探针的影响半径和过渡距离让插值平滑。6. 实际引擎里落地 PBRGamma、法线方向、反射探针这些翻车点原理和工作流都讲完了下面聊真实项目里最容易翻车的地方。这些都是我实际排查过、也帮别人擦过屁股的问题。6.1 Gamma 校正与线性空间为什么贴图颜色会“脏”PBR 的光照计算必须在线性空间进行但美术做贴图时看到的颜色是已经经过伽马编码sRGB的。如果引擎没把 sRGB 贴图转回线性再计算光照结果会偏亮、偏灰金属尤其明显。关键规则是Base Color 贴图是 sRGB需要在采样时标记为 sRGB引擎自动转线性。Roughness、Metallic、AO 贴图是线性数据千万别标记成 sRGB否则灰度值被提亮粗糙度偏高、金属度偏移整个材质表现会“糊一层雾”。Unreal 里贴图勾选 sRGB 的地方在 Texture 属性面板Unity 里在 Texture Import Settings 的 Color Space 选项。我见过一个真实案例一个车漆材质在所有引擎里都发灰排查到最后发现 roughness 贴图被误标成了 sRGB。修正后高光立刻收敛金属质感马上出来了。这类问题用白炉测试能快速定位。6.2 法线贴图方向DirectX 还是 OpenGL 协议法线贴图有两种坐标约定DirectX 约定绿色通道 Y 向下和 OpenGL 约定绿色通道 Y 向上。glTF、Blender、Marmoset 默认 OpenGL 约定Unity 用左手坐标系默认也是 OpenGL 约定但导入时可以在 Normal Map 设置里选择Unreal 本质上按 DirectX 约定处理部分压缩格式。跨软件交接时如果忘记转换渲染出来的法线方向是反的凹凸感会变成凹陷感光照方向全部错乱。检查方法很简单在引擎里放一个方向光看法线贴图上的凸起是否迎着光产生正确亮面。反了就把贴图的绿色通道反转Unreal 里勾选 Flip Green ChannelUnity 里选修改法线贴图 Y 通道。6.3 从 Substance/Blender 导出到引擎最容易漏掉哪些设置导出 glTF/glb 时确认贴图颜色空间正确glTF 规范里 Base Color 是 sRGB其他是线性大多数 DCC 工具导出时已经处理好但手动拼材质时需要自查。不要直接压缩 Roughness 贴图到低质量纹理格式而丢失灰度细节粗糙度丢失细节会让高光变得死板。Substance Painter 导出模板选对引擎版本Unreal 模板会生成 ORMAO/Roughness/Metalness 打包在一张图里Unity 模板通常生成单独贴图。打包贴图能减少采样次数但要确保通道顺序一致。6.4 PBR 表现异常的排查顺序我见过大量材质异常问题下面这张表是通用的排查顺序症状可能原因验证方式金属发灰、没有高光金属度贴图被当 sRGB 采样检查贴图颜色空间暗部死黑、环境反射丢失反射探针没摆或探针分辨率过低场景里放一个高光球观察反射粗糙度完全没作用Roughness 值被填到 0 或 1 极端用中间值测试确认贴图通道正确高光溢出、过曝光照强度过高或 auto exposure 没调把光照强度降到正常物理范围检查白炉测试法线凸起变凹陷法线贴图左右手坐标不一致绿色通道翻转测试远看材质正常近看粗糙mip 层级与 roughness 不匹配调整预滤波环境贴图级数提高环境贴图分辨率7. 性能与质量平衡移动端和大型场景的 PBR 优化实践PBR 听起来“物理”很多人担心性能爆炸。其实 BRDF 本身就是几个点积和指数运算比后处理特效轻得多。PBR 带来的性能压力主要来自纹理采样、IBL 采样和反射探针数量。7.1 计算量到底贵在哪一次完整的直接光 PBR 计算大概就是几次点积、一个 GGX 法线分布、一个 Smith 几何项和一个 Schlick 菲涅尔。放在现代 GPU 上几百个光源乘以全屏像素也不是大问题。真正贵的是 IBL预滤波环境贴图如果分辨率太高显存带宽压力大。反射探针数量一多每个像素可能要插值多个探针的立方体贴图采样。移动端 half float 精度受限GGX 里的平方根和除法在低端 GPU 上会产生波动。所以优化的核心不是砍 BRDF 算法而是降采样、降探针、降精度。7.2 移动端降载方案环境贴图和反射探针使用 128 或 256 分辨率即可金属球反射的细节肉眼几乎分辨不出 256 和 512 的区别。预滤波环境贴图的粗糙度层级可以从 6 级减到 4 级配合 mip 偏差做插值。限制实时反射探针数量到 1 到 2 个其余用烘焙过环境光和静态反射。动态光源数量控制在 1 到 2 个且关闭多光源逐像素阴影。材质参数统一打包到贴图通道里比如 RRoughness、GMetalness、BAO放一张 ORM 贴图减少采样器数量。我做过一个移动端展厅项目初始版本每帧采 6 个探针低端机直接掉到 20 帧。把它压到 1 个场景级探针加 1 个局部探针地面、墙面反射改用预烘焙帧率回到 60画质差距在高刷新率屏幕上几乎看不出来。7.3 团队里参数统一管理的经验PBR 最怕的是“全家桶式”乱设参数。项目里几十上百个材质如果每个美术都有自己的 roughness 习惯最终效果一定失控。我的做法是在项目里维护一份材质参数基线表例如金属Roughness 0.1 到 0.4Metallic 1。塑料Roughness 0.3 到 0.6Metallic 0。布料Roughness 0.8 到 1Metallic 0并建议加一点次表面近似。皮肤Roughness 0.5 左右Metallic 0配合 SSS 贴图。同时规定所有贴图通道命名规范_BaseColor、_Normal、_ORM。导出前用白炉测试跑一遍确保没有能量泄露再交给引擎组。这样即使某个材质效果不对也能很快定位是贴图问题还是参数问题。7.4 用 glTF 做跨软件交接的中转格式如果你要在 Blender、Substance、Unreal、Unity 之间反复导资产强烈建议用 glTF 2.0 作为中转格式。它的 PBR 材质工作流就是 metallic-roughness导出时自动处理颜色空间和法线方向能减少很多“导出后变灰”的破事。唯一要注意的是 glTF 对材质表达有约束太复杂的 Shader 参数比如清漆层、SSS导进去会丢所以中转格式适合基础材质特殊效果到目标引擎里再单独调。最后再分享一点个人体会做 PBR 这几年我最深的感受是它的门槛不在公式而在于你是否愿意把“直觉”换成“物理规律”。最初我用 Blinn-Phong 调材质靠的是一遍遍试高光指数切到 PBR 之后我反而少了很多盲目调试因为粗糙度、金属度、基础色三者的语义是明确的。你不需要背熟 Cook-Torrance 的每一项推导但你得知道 D、G、F 分别影响画面里的什么知道能量守恒必须在流程里被尊重知道反射探针比 shader 技巧更影响质感。如果看完这篇你只带走一件事那就是遇到材质表现不对劲先别急着调参数按贴图颜色空间、法线方向、反射探针、白炉测试这个顺序排查八成问题出在前两步。剩下的多做几个白模球放在环境里对比你的眼睛会慢慢建立起“物理正确感”这比任何教程都有用。