本章实测环境:Babylon.js9.30.0、Vite 8.3.4、TypeScript 5.9.3、Windows 11 + Chrome(WebGL2 后端)。
本章代码:src/chapters/ch14-pbr-channels.ts,运行后打开http://localhost:18000/?ch=14。
图中所有"源码出处"都指node_modules/@babylonjs/core里的真实文件与行号,你可以自己打开核对。
§14.1 本章要做成什么样
最终效果:一个"PBR 通道拆解实验室",展示一个金属球体,读者可以逐个开启/关闭 PBR 的各个通道(albedo、metallic、roughness、ambient、environment),实时观察每个通道对最终画面的贡献。右侧面板显示当前激活的通道列表和对应的纹理采样次数。场景中包含一个可切换的 HDRI 环境贴图,读者可以看到同一材质在不同环境下的表现差异。
直达链接:http://localhost:18000/?ch=14
为什么这章很重要:第 13 章介绍了 PBR 的概念,但没有深入讲解每个通道的具体作用。实际项目中,你需要理解 albedo、metallic、roughness、ambient 等贴图的用途,知道如何从 Substance Painter、Quixel Mixer 等工具导出正确的贴图,以及为什么环境贴图对金属材质至关重要。本章逐一拆解这些通道,让你能独立调试 PBR 材质问题。
§14.2 原理:PBR 材质的数据流
14.2.1 PBR 的输入与输出
PBR 材质的渲染流程可以简化为:
输入: - 几何数据:顶点位置、法线、UV - 材质参数:albedo、metallic、roughness、normal 等(标量或纹理) - 光照数据:直接光(方向光、点光源等)、间接光(环境贴图) - 相机数据:视图矩阵、投影矩阵 计算: - 顶点着色器:MVP 变换 - 片元着色器: 1. 采样 albedo 纹理 → 基础颜色 2. 采样 metallic/roughness 纹理 → 表面属性 3. 采样 normal 纹理 → 微表面法线 4. 采样 ambient occlusion 纹理 → 阴影遮蔽 5. 计算直接光照(漫反射 + 镜面反射) 6. 采样环境贴图 → 间接光照(IBL) 7. 混合所有贡献 → 最终颜色 输出: - 像素颜色(RGBA) - 深度值(用于深度测试)关键理解:PBR 不是单一公式,而是一套数据驱动的系统。每个通道(纹理)提供一部分信息,片元着色器把它们组合起来。如果某个通道缺失(如没有 metallic 纹理),系统会用默认值(通常是 0)替代。
14.2.2 通道之间的依赖关系
PBR 的各个通道不是独立的,它们之间存在复杂的交互:
metallic 决定反照率的用途:
metallic = 0(非金属):albedo 控制漫反射颜色,镜面反射颜色由菲涅尔效应自动计算(通常是灰色)。metallic = 1(金属):albedo 控制镜面反射颜色,漫反射几乎为零。
roughness 影响环境采样的 LOD:
roughness = 0(光滑):采样环境贴图的高清 mip level,得到清晰的反射。roughness = 1(粗糙):采样低清 mip level,得到模糊的反射。
ambient occlusion 调制间接光:
- AO 值低的地方(缝隙、角落)会减少间接光照,增强立体感。
- AO 不影响直接光照(方向光、点光源)。
理解这些依赖关系后,你才能正确调整材质参数,避免出现"金属看起来像塑料"或"反射太模糊"的问题。
§14.3 Albedo 通道:基础颜色
14.3.1 什么是 Albedo
Albedo(反照率)是物体表面的基础颜色,不含任何光照信息。它表示物体在均匀白光照射下呈现的颜色。
重要区分:
- Albedo ≠ Diffuse:Diffuse 可能包含阴影和高光信息(来自烘焙),Albedo 必须是"平坦"的颜色。
- Albedo 应该是线性空间的颜色:大多数贴图是 sRGB 格式的,Babylon.js 会自动转换到线性空间进行计算。确保你的贴图标记为
sRGB(默认就是)。
源码位置:Materials/PBR/pbrMaterial.pure.d.ts:63-65
/** * AKA Diffuse Texture in standard nomenclature. */accessor albedoTexture:Nullable<BaseTexture>;/** * Gets or sets the albedo color of the material. */accessor albedoColor:Color3;14.3.2 Albedo 贴图的规范
从 Substance Painter 或 Quixel 导出 Albedo 贴图时,遵循以下规范:
- 无阴影、无高光:只保留物体的固有色。如果有烘焙的阴影,用 Photoshop 去掉。
- 中性灰度平衡:对于金属,Albedo 应该是金属的真实颜色(金 = 黄色,铜 = 橙红色)。对于非金属,Albedo 通常是灰色或彩色。
- 分辨率适中:512×512 或 1024×1024 足够大多数场景。过高的分辨率浪费显存,过低会导致模糊。
- 文件格式:PNG(无损)或 JPEG(有损,但体积小)。对于压缩纹理,使用 KTX2/DDS(见第 15 章)。
常见错误:
- Albedo 太暗:导致整体画面发黑。PBR 的能量守恒会进一步降低亮度。修复:在 Photoshop 里提高亮度,或在 Babylon.js 里乘以系数:
material.albedoColor.scaleInPlace(1.5)。 - Albedo 包含高光:导致金属反射颜色错误。修复:去掉高光,只保留固有色。
14.3.3 动手实验:观察 Albedo 的影响
import{PBRMaterial,Color3,Texture}from'@babylonjs/core'constpbrMat=newPBRMaterial('pbrMat',scene)// 方法 1:纯色pbrMat.albedoColor=newColor3(0.8,0.2,0.2)// 红色// 方法 2:纹理pbrMat.albedoTexture=newTexture('./assets/albedo.png',scene)pbrMat.albedoTexture.hasAlpha=false// Albedo 通常不包含透明度// 关闭其他通道,只看 Albedo 的效果pbrMat.metallic=0pbrMat.roughness=1pbrMat.environmentIntensity=0pbrMat.directIntensity=1.0运行后,你应该看到一个纯红色的球体(如果用纯色)或带有纹理图案的球体(如果用纹理)。因为没有金属度和粗糙度的变化,也没有环境光,画面看起来比较"平"。
§14.4 Metallic 与 Roughness 通道:表面属性
14.4.1 Metallic:金属还是非金属
Metallic(金属度)是一个 0-1 的标量,决定物体是金属还是非金属:
metallic = 0:非金属(绝缘体),如塑料、木材、陶瓷。漫反射强,镜面反射弱且颜色为灰色。metallic = 1:纯金属(导体),如金、银、铝。漫反射几乎为零,镜面反射强且颜色为金属的固有色。0 < metallic < 1:混合状态,通常用于模拟生锈的金属(锈迹部分是非金属,未锈部分是金属)。
物理依据:金属的自由电子会吸收大部分入射光,只有表面反射的光能逃逸,所以金属几乎没有漫反射。非金属的电子束缚较强,光线能进入内部散射后再出来,形成漫反射。
源码位置:Materials/PBR/pbrMaterial.pure.d.ts:108-115
/** * Specifies the metallic scalar of the metallic/roughness workflow. * Can also be used to scale the metalness values of the metallic texture. */accessor metallic:Nullable<number>;/** * Stores the metallic values in a texture. * Typically stored in the B channel of a packed texture. */accessor metallicTexture:Nullable<BaseTexture>;14.4.2 Roughness:光滑还是粗糙
Roughness(粗糙度)是一个 0-1 的标量,决定表面的微观粗糙程度:
roughness = 0:完全光滑,镜面反射清晰如镜子。roughness = 1:完全粗糙,镜面反射扩散成均匀的漫反射。0 < roughness < 1:中间状态,镜面反射模糊但仍有方向性。
物理依据:粗糙表面由朝向各异的微表面组成。入射光被这些微表面反射到不同方向,形成模糊的高光。光滑表面的微表面朝向一致,反射光集中在一个方向,形成清晰的高光。
Roughness 与环境采样的关系:
Babylon.js 的环境贴图是多 mip level 的。渲染时,根据 roughness 值选择对应的 mip level:
roughness = 0→ mip level 0(最高清)roughness = 1→ mip level N(最模糊)
这样做的目的是模拟粗糙表面的模糊反射,而不需要昂贵的实时光线追踪。
源码位置:Materials/PBR/pbrMaterial.pure.d.ts:116-120
/** * Specifies the roughness scalar of the metallic/roughness workflow. * Can also be used to scale the roughness values of the metallic texture. */accessor roughness:Nullable<number>;14.4.3 Metallic-Roughness 工作流 vs Specular-Glossiness 工作流
PBR 有两种主流工作流:
| 特性 | Metallic-Roughness | Specular-Glossiness |
|---|---|---|
| 参数 | metallic (0-1), roughness (0-1) | specular (RGB), glossiness (0-1) |
| 优点 | 参数少,直观,glTF 标准 | 更灵活,可以模拟非物理的材质 |
| 缺点 | 无法模拟某些特殊材质(如导电塑料) | 参数多,不易调整 |
| Babylon.js 支持 | ✅ PBRMaterial 唯一的工作流 | ⚠️ 材质上没有开关,靠 glTF 加载器换算 |
推荐:除非有特殊需求,否则使用 Metallic-Roughness 工作流。它是 glTF 2.0 的标准,兼容性最好。
补一句实测口径:useSpecularGlossinessInput这个属性在 v9.30.0 的PBRMaterial/PBRBaseMaterial上不存在,材质层没有「切成 specular-glossiness」的开关——microSurface(光泽度)只是同一套着色器的反着写法。真正的 Specular-Glossiness 支持在导入环节:@babylonjs/loaders里有 KHR_materials_pbrSpecularGlossiness 这个归档扩展的实现(Materials/PBR/pbrMetallicRoughnessMaterial.d.ts:11附了规范链接),加载 .glb 时替你换算成 metallic/roughness。所以「手上只有 specular-glossiness 贴图」的正确解法是走 glTF,而不是找那个不存在的开关。
14.4.4 打包纹理:Metallic + Roughness + AO
为了节省纹理采样次数和显存,通常把 metallic、roughness、ambient occlusion 打包到一张纹理的不同通道:
- R 通道:Ambient Occlusion
- G 通道:Roughness
- B 通道:Metallic
- A 通道:未使用(或存储其他数据)
这种纹理叫ORM 纹理(Occlusion-Roughness-Metallic)。但 Babylon.js不会自动认 ORM:metallicTexture挂上去之后,引擎默认只把Alpha 通道当 roughness,R、G、B 一概不采。要它按 ORM 的约定取值,得把四个通道开关逐个打开:
// 加载 ORM 纹理constormTexture=newTexture('./assets/orm.png',scene)pbrMaterial.metallicTexture=ormTexture// 默认 true / false / false / false —— 只认 A 通道的 roughnesspbrMaterial.useRoughnessFromMetallicTextureAlpha=false// 必须先关掉 A,G 的开关才生效pbrMaterial.useRoughnessFromMetallicTextureGreen=true// G = RoughnesspbrMaterial.useMetallnessFromMetallicTextureBlue=true// B = MetallicpbrMaterial.useAmbientOcclusionFromMetallicTextureRed=true// R = Ambient Occlusion源码位置:Materials/PBR/pbrMaterial.pure.d.ts:254(Alpha)、:259(Green,注释写着 “Needs useRoughnessFromMetallicTextureAlpha to be false”)、:263(Blue)、:267(Red);默认值在Materials/PBR/pbrBaseMaterial.pure.js:510-525,四个开关翻成 shader define 在:1299-1302。
两个名字坑。第一,拼写是useMetallness...(metallness,三个 l),跟标量属性metallic不同源,你按useMetallic去 grep 是搜不到它的;useMetallicFromMetallicTexture、useRoughnessFromMetallicTexture(不带通道名)、useAmbientOcclusionFromMetallicTexture这三个在包里都不存在。第二,「R=AO / G=Roughness / B=Metallic」是 glTF 的约定,不是引擎的默认值——正因为默认约定不一致,才有下面这个坑(§14.8 坑 14-02)。
优势:
- 减少纹理采样次数:从 3 次降到 1 次。
- 减少显存占用:一张纹理代替三张。
- 提高缓存命中率:GPU 纹理缓存更高效。
劣势:
- 每个通道只有 8 位精度(如果使用 PNG/JPEG),可能导致带状伪影。解决方法:使用 16 位纹理格式(如 KTX2 with BC7 compression)。
- 无法独立调整各个通道的 uScale/uOffset(见第 15 章)。
§14.5 Ambient Occlusion 通道:接触阴影
14.5.1 什么是 Ambient Occlusion
Ambient Occlusion(环境光遮蔽,AO)是一种近似全局光照的技术。它模拟物体表面因周围几何体遮挡而接收较少间接光的现象。
直观理解:想象一个房间角落里有两个箱子靠在一起。箱子接触的缝隙处会比箱子的正面更暗,因为缝隙处接收的天空光更少。AO 贴图就是预先计算好的这种"暗度"信息。
AO 的特点:
- 静态:AO 通常在建模软件(Blender、Maya)或烘焙工具(Substance Painter)中预计算,运行时不变。
- 只影响间接光:AO 不遮挡直接光照(方向光、点光源),只减弱环境光和 IBL。
- 灰度图:AO 贴图是单通道的灰度图,白色 = 无遮蔽,黑色 = 完全遮蔽。
源码位置:Materials/PBR/pbrMaterial.pure.d.ts:75-80
/** * AKA Occlusion Texture in other nomenclature. */accessor ambientTexture:Nullable<BaseTexture>;/** * AKA Occlusion Texture Intensity in other nomenclature. */accessor ambientTextureStrength:number;14.5.2 AO 贴图的生成
从 Blender 导出 AO 贴图的步骤:
- 在 Blender 中选中模型,进入 Shader Editor。
- 添加 “Ambient Occlusion” 节点,连接到 “Principled BSDF” 的 “AO” 输入。
- 烘焙 AO 到纹理:Render → Bake → Bake Type = Ambient Occlusion。
- 导出为 PNG 或嵌入到 ORM 纹理的 R 通道。
注意事项:
- AO 贴图的分辨率可以与 Albedo 不同(通常更低,如 512×512),因为 AO 是低频信息。
- AO 贴图应该无缝拼接(如果模型需要平铺)。
- 避免过度烘焙:AO 值不应该低于 0.3,否则缝隙会太黑。
14.5.3 AO 强度的调节
ambientTextureStrength控制 AO 的影响程度:
strength = 0:AO 完全无效。strength = 1:AO 完全生效(默认值)。strength > 1:AO 效果增强,可能导致缝隙过黑。
建议:保持strength = 1,在烘焙阶段调整 AO 的对比度,而不是在运行时调节强度。
§14.6 环境贴图与 IBL:让金属"活"起来
14.6.1 为什么金属需要环境贴图
回顾第 13 章的知识:金属的漫反射几乎为零,所有可见的颜色都来自镜面反射。如果没有环境贴图,金属无法反射任何东西,看起来就是黑色的。
IBL(Image-Based Lighting)的原理:
- 用一张 HDRI(高动态范围图像)包裹整个场景,作为无限远的环境光源。
- 预过滤这张 HDRI,生成多个 mip level,对应不同的 roughness 值。
- 渲染时,根据片元的 roughness 值采样对应 mip level 的环境贴图,得到间接光照。
这样,金属就能反射环境中的内容(天空、建筑物、其他物体),看起来"活"起来。
14.6.2 加载环境贴图
Babylon.js 支持多种格式的环境贴图:
方法 1:从预过滤的 .env 文件加载
// 只吃 .env:里面是别人(IBL Baker、Lys、Babylon Sandbox)预先过滤好的 mip 链 + 球谐系数constenvTexture=CubeTexture.CreateFromPrefilteredData('./assets/environment.env',scene)pbrMaterial.environmentTexture=envTexture pbrMaterial.environmentIntensity=1.0.env是 Babylon.js 专有的预过滤格式,首帧不用再做一遍预过滤,省的是这一步的功夫(本书没有做过 .env 与 .hdr 的加载耗时对比,别把「快 10 倍」这类数字抄进项目文档)。关键是扩展名必须真的是 .env:把 .hdr 改名成 .env 不会得到预过滤数据,只得到一次加载失败。
方法 2:从 HDRI 文件加载(运行时预过滤)
// .hdr / .exr 走 HDRCubeTexture,第三个参数 size(立方图边长)必填constenvTexture=newHDRCubeTexture('./assets/hdri/studio_small_03_1k.hdr',scene,1024)注意这两个入口不能混用:CreateFromPrefilteredData是CubeTexture上按 .env 解析的静态工厂,拿它加载 .hdr 是不对的写法;反过来说,把 .env 传给HDRCubeTexture也一样错。本书public/assets/hdri/下是 Poly Haven 的三个 .hdr,仓库里没有任何 .env,所以正文和分步示例统一走HDRCubeTexture。
方法 3:使用默认环境
scene.createDefaultEnvironment({createSkybox:true,createGround:true,environmentIntensity:1.0,groundColor:newColor3(0.3,0.3,0.3)})这会创建一个简单的渐变天空盒和地面,适合快速原型。
源码位置:Materials/Textures/cubeTexture.pure.d.ts:182-190、cubeTexture.pure.js:469(把这个自由函数挂成CubeTexture.CreateFromPrefilteredData)
/** * Creates and return a texture created from prefilterd data by tools like IBL Baker or Lys. * @param url defines the url of the prefiltered texture * @param scene defines the scene the texture is attached to * @param forcedExtension defines the extension of the file if different from the url * @param createPolynomials defines whether or not to create polynomial harmonics from the texture data if necessary * @returns the prefiltered texture */exportdeclarefunctionCubeTextureCreateFromPrefilteredData(url:string,scene:Scene,forcedExtension?:any,createPolynomials?:boolean):CubeTexture;引擎注释里的原文是 “prefilterd”(就这个拼写),而参数说明只提 “the url of the prefiltered texture”,没有说它能吃 HDR 文件——所以「.env 或 .hdr 都行」这种写法不要信。
14.6.3 环境贴图的来源
推荐的免费 HDRI 资源:
| 网站 | 许可证 | 特点 |
|---|---|---|
| Poly Haven | CC0 | 高质量,专为 PBR 优化 |
| HDRI Haven | CC0 | 大量室内/室外场景 |
| ambientCG | CC0 | 同时提供 HDRI 和 PBR 材质 |
下载建议:
- 选择 2K-4K 分辨率的 HDRI(更高分辨率收益递减)。
- 优先选择
.hdr或.exr格式(高动态范围)。 - 如果网站提供
.env格式,直接下载使用(已预过滤)。
14.6.4 环境强度的调节
environmentIntensity控制环境光照的整体亮度:
intensity = 0:环境光完全关闭,金属变黑。intensity = 1:正常亮度(默认值)。intensity > 1:环境光增强,适合夜间场景或需要强调反射的情况。
技巧:如果金属反射太强,降低environmentIntensity;如果反射太弱,提高 intensity 或更换更亮的 HDRI。
§14.7 预期输出与自查清单
✅成功标志:
- 金属球体有清晰的反射,能看到环境贴图的内容(天空、建筑物等)。
- 拖动 roughness 滑块时,反射从清晰逐渐变模糊。
- 拖动 metallic 滑块时,球体从塑料感变成金属感。
- 开启/关闭 AO 通道时,缝隙处的明暗变化明显。
- Inspector 显示环境贴图已加载,mip levels 数量 ≥ 8。
❌失败标志及修复:
- 金属球体是黑色的:缺少环境贴图。调用
scene.createDefaultEnvironment()或手动设置environmentTexture。 - 反射太模糊:环境贴图的 mip levels 不足或 roughness 值太高。检查 HDRI 分辨率,或使用更高清的环境贴图。
- AO 效果不明显:
ambientTextureStrength太低或 AO 贴图对比度不足。提高 strength 或重新烘焙 AO。 - Albedo 颜色发灰:贴图可能在 sRGB 和线性空间之间转换错误。确保
texture.isSRGB = true(默认就是)。
§14.8 常见坑与出处
14-01:环境贴图加载异步导致首帧黑屏
现象:页面加载后,金属球体先是黑色,几秒后才出现反射。
原因:环境贴图是异步加载的,构造函数或静态工厂返回的瞬间对象就有了,但纹素还在网络上飞——赋值成功不等于数据到位。
修复:
constenvTexture=newHDRCubeTexture('./assets/hdri/studio_small_03_1k.hdr',scene,1024)envTexture.onLoadObservable.add(()=>{console.log('Environment texture loaded')// 可选:在这里触发重新渲染或显示加载完成提示})pbrMaterial.environmentTexture=envTexture或者使用scene.createDefaultEnvironment(),它会自动处理异步加载并显示进度条。
源码位置:Materials/Textures/baseTexture.pure.d.ts:298(isReadyOrNotBlocking()方法)
14-02:ORM 纹理通道混淆
现象:设置了 ORM 纹理后,金属度或粗糙度效果异常(如应该光滑的地方很粗糙)。
原因:多半不是工具导出错了顺序,而是 Babylon.js 的默认约定跟 ORM 的约定不一样。useRoughnessFromMetallicTextureAlpha默认true,另外三个通道开关默认全false(pbrBaseMaterial.pure.js:510-525)——也就是说引擎只读 A 通道的 roughness,R 的 AO、G 的 roughness、B 的 metallic 一个都没被采样。于是症状是「金属度永远是 0、AO 毫无作用、roughness 跟着贴图的透明通道跑」,看着像贴图坏了,其实是开关没开。
修复:按通道打开对应开关,四个名字以.d.ts为准(pbrMaterial.pure.d.ts:251-267):
pbrMaterial.metallicTexture=ormTexture pbrMaterial.useRoughnessFromMetallicTextureAlpha=false// 关掉默认的 A 通道,否则 G 的开关无效pbrMaterial.useRoughnessFromMetallicTextureGreen=true// G = RoughnesspbrMaterial.useMetallnessFromMetallicTextureBlue=true// B = Metallic(metallness 三个 l)pbrMaterial.useAmbientOcclusionFromMetallicTextureRed=true// R = Ambient OcclusionuseMetallicFromMetallicTextureGreenChannel/useMetallicFromMetallicTextureBlueChannel这两个名字不存在,写上去 TypeScript 编译就过不去。
更省事的方法:直接用 glTF 资产(第 32 章),加载器替你把这些开关配好——@babylonjs/loaders在glTF/2.0/pbrMaterialLoadingAdapter.js:210-219里就是先useRoughnessFromMetallicTextureGreen = true、再useRoughnessFromMetallicTextureAlpha = !value、最后开 Blue;或者在 Substance Painter / Photoshop 里把 roughness 挪进 A 通道,保持引擎的默认约定不动。
14-03:Albedo 贴图包含 Alpha 通道导致透明伪影
现象:金属表面出现奇怪的透明区域或边缘锯齿。
原因:Albedo 贴图的 Alpha 通道不是完全不透明(255),导致材质误认为某些区域是透明的。
修复:
pbrMaterial.albedoTexture.hasAlpha=false// 明确告诉引擎忽略 Alpha 通道或者在图像处理软件里删除 Alpha 通道,保存为 RGB 格式。
14-04:环境贴图与天空盒不一致
现象:金属反射的环境内容与背景天空盒不匹配。
原因:使用了不同的 HDRI 作为环境贴图和天空盒,或者天空盒的旋转角度与环境贴图不一致。
修复:
// 使用同一张环境贴图作为环境贴图和天空盒constenvTexture=newHDRCubeTexture('./assets/hdri/studio_small_03_1k.hdr',scene,1024)pbrMaterial.environmentTexture=envTexture// 创建天空盒(按 §5.3.2 的约定,网格加 mesh- 前缀、材质加 mat- 前缀)constskybox=MeshBuilder.CreateBox('mesh-skybox',{size:1000},scene)constskyboxMat=newStandardMaterial('mat-skybox',scene)skyboxMat.backFaceCulling=falseskyboxMat.reflectionTexture=envTexture.clone()// 克隆以避免共享状态(CubeTexture.clone() 在 cubeTexture.pure.d.ts:172)skyboxMat.reflectionTexture.coordinatesMode=Texture.SKYBOX_MODEskyboxMat.disableLighting=trueskybox.material=skyboxMat确保reflectionTexture.coordinatesMode = Texture.SKYBOX_MODE,这样天空盒的旋转会与环境贴图同步。
§14.9 章节挑战
挑战任务:创建一个"材质展示台",包含四个球体,分别模拟以下材质,并为每个材质配置完整的 PBR 通道:
生锈的铁板:
- Albedo:铁锈的红褐色 + 未锈部分的灰色(使用遮罩混合)
- Metallic:生锈部分 = 0,未锈部分 = 1(使用纹理)
- Roughness:生锈部分 = 0.8,未锈部分 = 0.3
- AO:缝隙和凹陷处较暗
- Environment:工业风格的 HDRI(仓库或工厂)
抛光的大理石:
- Albedo:白色带灰色纹路
- Metallic:0(非金属)
- Roughness:0.1(非常光滑)
- Normal:细微的表面凹凸(可选,见第 17 章)
- Environment:明亮的室内 HDRI
阳极氧化铝:
- Albedo:蓝色或紫色(阳极氧化着色)
- Metallic:1
- Roughness:0.2
- Clear Coat:启用,模拟表面透明氧化层(见第 17 章)
- Environment:工作室 HDRI
旧皮革:
- Albedo:深棕色,带有磨损痕迹
- Metallic:0
- Roughness:0.7
- AO:褶皱处较暗
- Sheen:启用,模拟布料的柔和高光(见第 17 章)
- Environment:温馨的室内 HDRI
验收标准:
- 四个球体排列整齐,每个球体下方有标签说明材质名称。
- 生锈铁板的金属和非金属区域过渡自然。
- 大理石球体有清晰的反射,能看到环境贴图的倒影。
- 阳极氧化铝有两层高光:底层的金属反射和表层的清漆反射。
- 旧皮革有柔和的表面质感,没有过于尖锐的高光。
提示:对于生锈铁板,可以使用遮罩纹理混合两种 metallic/roughness 值。Babylon.js 的 PBRMaterial 支持纹理混合,但需要自定义着色器或使用 Node Material Editor(见第 18 章)。简单做法是在 Substance Painter 里直接绘制 metallic/roughness 纹理。
§14.10 本章小结
本章深入讲解了 PBR 材质的各个通道:
- Albedo:基础颜色,不含光照信息。应该是"平坦"的固有色。
- Metallic:决定物体是金属还是非金属。金属几乎没有漫反射,所有颜色来自镜面反射。
- Roughness:决定表面的微观粗糙程度。影响环境采样的 mip level,控制反射的模糊程度。
- Ambient Occlusion:模拟接触阴影,只影响间接光。通常与 metallic/roughness 打包成 ORM 纹理。
- Environment / IBL:基于图像的光照,从 HDRI 采样间接光。对金属材质至关重要,让金属"活"起来。
理解这些通道的作用和相互关系后,你就能独立调试 PBR 材质问题,知道从哪里入手调整参数。下一章我们将讲解贴图与 UV 映射,包括 mipmap、各向异性过滤、压缩纹理等高级主题。
§14.11 术语卡
| 中文 | English | 一句话解释 |
|---|---|---|
| 反照率 | Albedo | 物体表面的基础颜色,不含光照信息 |
| 金属度 | Metallic | 0 = 非金属,1 = 纯金属 |
| 粗糙度 | Roughness | 0 = 完全光滑,1 = 完全粗糙 |
| 环境光遮蔽 | Ambient Occlusion (AO) | 模拟缝隙和角落因遮挡而变暗的效果 |
| IBL | Image-Based Lighting | 基于图像的光照,从环境贴图采样间接光 |
| HDRI | High Dynamic Range Image | 高动态范围图像,包含超出 0-1 范围的亮度信息 |
| ORM 纹理 | Occlusion-Roughness-Metallic Texture | 将 AO、Roughness、Metallic 打包到一张纹理的三个通道 |
| Mip Level | Mipmap Level | 纹理的多级细节版本,用于加速采样和减少别名 |
| 预过滤 | Prefiltering | 预先计算环境贴图的多个粗糙度版本,加速运行时采样 |
| 能量守恒 | Energy Conservation | 反射光能 ≤ 入射光能,PBR 的核心原则 |