Skip to main content

Chapter 32: Advanced Material Models and Microfacet BRDF

这一章要把复杂材质从“更多参数”还原成一条可追踪的着色路径:一个 fragment 拿到法线、视线、光线、材质贴图和环境光之后,如何用微表面 BRDF 计算反射,如何把吸收、透射、清漆、织物绒感和各向异性放入同一套材质系统,最后如何判断视觉差异来自公式、贴图、法线空间、环境反射还是性能降级。

贯穿本章的材料是一颗放在 HDR 环境光和一盏主光下的测试球。它使用同一份几何、同一张法线贴图和同一套环境贴图,只切换材质参数:金属、塑料、玻璃、布料、皮肤近似和带清漆的车漆。读者读完后应能定位高光形状、掠射角反射、透射模糊、绒边亮度和材质成本分别由哪一个 BRDF 项、哪一种贴图或哪条 shader 分支控制。

高级材质模型的核心判断是:先建立基础微表面镜面反射,再把进入表面的能量按吸收、散射、透射和多层反射重新分配。实时渲染中的 PBR 材质通常使用工程近似,它追求跨光照条件的稳定外观、可编辑参数和可控成本。Google Filament 的 Physically Based Rendering in Filament 文档用 DGF 三项解释实时微表面 BRDF;Khronos glTF 的 KHR_materials_clearcoatKHR_materials_transmissionKHR_materials_sheenKHR_materials_anisotropy 扩展则展示了复杂材质如何落成资产参数、贴图通道和分层规则。

本章的检查顺序保持固定:先看基础 D/G/F 是否稳定,再看能量是否在 base、specular、clearcoat、sheen、transmission 之间合理分配,再看 normal / tangent / texture channel 是否正确,最后才讨论 LUT、预积分、材质分级和 shader variant 成本。

32.1 微表面模型原理

微表面模型把一个宏观表面看成大量微小镜面片段的统计结果。测试球在屏幕上只显示一个像素或一个 fragment,但 shader 计算时会假设这个 fragment 覆盖的微区域里存在许多朝向不同的微面。每个微面仍然按镜面反射工作;宏观高光的大小、亮度和拖尾来自这些微面法线的分布。

Cook-Torrance 常见实时写法可以压缩成 $f_r = \frac{D(h, \alpha)G(l, v, \alpha)F(v, h)}{4(n \cdot l)(n \cdot v)}$。这里 n 是宏观或扰动后的表面法线,l 是入射光方向,v 是视线方向,h 是半程向量,alpha 通常由 roughness 映射而来。这个式子直接对应测试球上的三个可观察结果:D 决定高光集中程度,G 决定微面互相遮挡后的能量损失,F 决定视角变化时反射比例。

D 是法线分布函数(Normal Distribution Function)。它回答“有多少微面刚好朝向半程向量”。粗糙度低时,大量微面集中在宏观法线附近,D 的峰值高,高光小且亮。粗糙度高时,微面朝向分散,D 的峰值降低,高光变宽。GGX / Trowbridge-Reitz 在实时 PBR 中常用,因为它有长尾,高粗糙表面仍保留较自然的掠射角反射。

G 是几何项(Geometry Term),也常写成 visibility 或 masking-shadowing。它回答“朝向正确的微面是否能被光照到,并且是否能被相机看到”。在测试球的暗边附近,光线方向和视线方向都接近表面切线,微面之间互相遮挡增多,G 会降低贡献。没有这个项时,粗糙材质的边缘和暗部容易产生过亮的非物理高光。

F 是 Fresnel 项。它回答“入射到界面的能量有多少被反射回外部”。对塑料、陶瓷、水、皮肤这类电介质,正视角反射通常较低,掠射角反射升高;对金属,反射颜色本身带有材质颜色,漫反射贡献接近零。Schlick 近似常用于实时 shader,因为它把角度变化压成少量乘加和一次五次方近似。

下面这段 GLSL 展示了最小镜面 BRDF 结构。它省略了多灯循环、IBL、阴影和多层材质,目的只在于让 D/G/F 的数据依赖可见。

const float PI = 3.14159265359;

float saturate(float x) {
return clamp(x, 0.0, 1.0);
}

float distributionGGX(float NoH, float roughness) {
float alpha = roughness * roughness;
float alpha2 = alpha * alpha;
float denom = NoH * NoH * (alpha2 - 1.0) + 1.0;
return alpha2 / max(PI * denom * denom, 1e-5);
}

float geometrySmithGGX(float NoV, float NoL, float roughness) {
float alpha = roughness * roughness;
float k = (alpha + 1.0) * (alpha + 1.0) * 0.125;
float gv = NoV / max(NoV * (1.0 - k) + k, 1e-5);
float gl = NoL / max(NoL * (1.0 - k) + k, 1e-5);
return gv * gl;
}

vec3 fresnelSchlick(float VoH, vec3 f0) {
float oneMinus = 1.0 - saturate(VoH);
float factor = oneMinus * oneMinus * oneMinus * oneMinus * oneMinus;
return f0 + (1.0 - f0) * factor;
}

vec3 evaluateSpecularBRDF(vec3 normal, vec3 viewDir, vec3 lightDir, vec3 f0, float roughness) {
vec3 halfDir = normalize(viewDir + lightDir);
float NoV = saturate(dot(normal, viewDir));
float NoL = saturate(dot(normal, lightDir));
float NoH = saturate(dot(normal, halfDir));
float VoH = saturate(dot(viewDir, halfDir));

float d = distributionGGX(NoH, roughness);
float g = geometrySmithGGX(NoV, NoL, roughness);
vec3 f = fresnelSchlick(VoH, f0);

return d * g * f / max(4.0 * NoV * NoL, 1e-5);
}

这段代码里的 roughness 同时影响 DG。测试时只修改 roughness,若高光宽度变化正常但暗边亮度异常,应优先检查 G 或分母中的 NoV / NoL 保护。若正视角和掠射角反射差异异常,应检查 F0、metallic 混合、颜色空间和法线方向。

微表面模型还要求区分宏观法线和切线空间扰动法线。normal map 改变的是 shader 中的局部表面朝向,它会影响 NoLNoVNoHDGF 的输入。几何轮廓仍由 mesh 决定,所以一张强法线贴图可以改变表面高光纹理,却不会改变球体真实轮廓。复杂材质排查时,先把 normal map 关闭可以快速判断问题来自 BRDF 参数还是来自切线空间。

32.2 光子吸收与散射模拟

实时材质中的“光子吸收与散射模拟”更准确地说是能量路径归类。shader 通常没有逐光子追踪;它把入射能量分成表面反射、进入介质后的吸收、体内散射、透射和多层反射几类,再用贴图和近似公式控制每类比例。这个归类能解释测试球上的玻璃透光、车漆清漆、布料绒边和皮肤软阴影。

吸收(absorption)描述光进入介质后某些波长被材料消耗。红色玻璃让红光保留更多,蓝绿通道被吸收更多;最终表现为透射光和内部路径带有颜色。实时薄表面透明常用 baseColor 或 transmission tint 近似吸收;有厚度信息时,可以把 thickness、attenuation color 和 attenuation distance 组合起来近似 Beer-Lambert 衰减。

散射(scattering)描述光进入材料后方向被多次改变。皮肤、蜡、玉石和牛奶玻璃的视觉差异主要来自散射距离、吸收颜色和出射位置。上一章的 SSS 已经覆盖皮肤散射,本章只把它放回高级材质模型:当材质存在明显内部散射时,单一表面 BRDF 只能解释表面反射,diffuse 或 subsurface 项要承担进入介质后的能量再分配。

透射(transmission)描述光穿过表面或薄介质。Khronos 的 KHR_materials_transmission 把 transmissionFactor 定义为进入表面后被透射的比例,并强调它服务薄表面透明,如玻璃和透明塑料。对测试球来说,transmissionFactor 控制背景能否穿过球体可见,roughness 控制透射背景的模糊程度,Fresnel 控制掠射角仍然保留强反射。

clearcoat 是覆盖在基础材质上的薄反射层。Khronos 的 KHR_materials_clearcoat 把 clearcoat 表达为 layered microfacet BRDF:基础 metallic-roughness 材质先计算,再在上方叠加一个由 clearcoatFactor、clearcoatRoughness 和 clearcoatNormalTexture 控制的清漆层。车漆测试球会同时出现底层颜色和顶层锐利白色高光;如果只看到底层漫反射,clearcoatFactor 或清漆层法线绑定通常存在问题。

sheen 用来表达布料、天鹅绒和微纤维表面的掠射角柔亮。Khronos 的 KHR_materials_sheen 将 sheen 层放在 metallic-roughness 基础材质之上,并通过 sheenColor 和 sheenRoughness 控制绒感颜色与宽度。布料测试球在正视角可能接近哑光,边缘会出现有颜色的柔亮边。这个现象来自微纤维的后向散射近似,和金属高光的镜面反射形态不同。

anisotropy 描述高光沿某个切线方向拉伸。拉丝金属、头发、织物纤维和刷痕塑料常见这种外观。Khronos 的 KHR_materials_anisotropy 使用 anisotropyStrength、anisotropyRotation 和 anisotropyTexture,把高光伸展方向放入 tangent / bitangent 空间。测试球上若旋转模型后拉伸方向跟着 UV 或切线旋转,说明切线空间参与了 BRDF;若方向固定在屏幕上,通常是 tangent basis 或 normal transform 错误。

这些扩展共同说明一个分层材质规律:每一层都应有清晰输入、输出和能量分配位置。基础层处理 diffuse、metallic 和 roughness;clearcoat 拿走一部分顶层 Fresnel 反射;sheen 改变纤维表面的边缘贡献;transmission 处理进入表面后穿出的能量;anisotropy 改变 NDF 在切线空间中的形状。复杂材质失真时,按层关闭比直接调参更可靠。

下面的 Mermaid 图把测试球的一次材质评估压成可追踪路径。图中每个节点都对应 shader 中的一组输入、公式或资源读取。

这条路径的关键点是输入先被统一到同一坐标语境,再进入各层 BRDF。direct light 需要明确 l,IBL 则常用预过滤环境贴图和 BRDF LUT 近似半球积分。材质层越多,越需要把每层的输入法线、粗糙度、贴图通道和能量权重拆开调试。

32.3 实践:Shader 实现复杂 PBR 材质

复杂 PBR shader 的实现应先固定数据结构。测试球需要的最小材质输入包括 baseColorroughnessmetallicnormalemissiveocclusionclearcoatclearcoatRoughnesstransmissionsheenColorsheenRoughnessanisotropyStrengthanisotropyRotation。这些输入来自 uniform、材质 buffer 或贴图通道,进入 shader 前要明确颜色空间和取值范围。

材质参数读取的第一道校验是通道语义。baseColor 贴图通常按 sRGB 读取并转到 linear space 参与光照;roughness、metallic、normal、AO、transmission、clearcoat 这类数据贴图应按 linear data 读取。若 roughness 贴图被当作 sRGB,低值区域会被错误抬高或压低,高光宽度会失真。若 metallic 和 roughness 通道打包顺序错误,塑料可能呈现金属反射,金属可能出现灰白漫反射。

第二道校验是 F0。电介质常用约 0.04 作为正视角反射率近似,金属的 F0 来自 baseColor 或专门的 specular color。metallic 工作流通常写成 f0 = mix(vec3(0.04), baseColor, metallic),同时 diffuse 权重使用 (1.0 - metallic) 衰减。这个设计让塑料保留有色漫反射和白色高光,让金属使用有色镜面反射并压低漫反射。

第三道校验是 IBL 路径。直接光计算只评估少量光源方向;环境光需要近似半球积分。常见实时做法是 diffuse irradiance map 负责低频漫反射,prefiltered radiance map 负责不同 roughness 下的镜面环境反射,BRDF LUT 负责把 NoV 和 roughness 对应的积分权重查出来。若测试球在主光下正确,在环境光下金属过黑或塑料边缘过亮,应优先检查 prefiltered mip、BRDF LUT、反射向量和颜色空间。

下面的简化 GLSL 展示复杂材质评估的组织方式。它保留分层顺序和校验点,省略具体 IBL 采样函数实现。

struct MaterialSample {
vec3 baseColor;
float roughness;
float metallic;
vec3 normal;
float occlusion;
float clearcoat;
float clearcoatRoughness;
vec3 clearcoatNormal;
float transmission;
vec3 sheenColor;
float sheenRoughness;
float anisotropyStrength;
};

vec3 evaluateDirectMaterial(
MaterialSample material,
vec3 viewDir,
vec3 lightDir,
vec3 lightColor,
vec3 tangent,
vec3 bitangent
) {
vec3 n = normalize(material.normal);
vec3 v = normalize(viewDir);
vec3 l = normalize(lightDir);
vec3 h = normalize(v + l);

float NoL = saturate(dot(n, l));
float NoV = saturate(dot(n, v));
float VoH = saturate(dot(v, h));

vec3 dielectricF0 = vec3(0.04);
vec3 f0 = mix(dielectricF0, material.baseColor, material.metallic);
vec3 specular = evaluateSpecularBRDF(n, v, l, f0, material.roughness);
vec3 diffuse = material.baseColor * (1.0 - material.metallic) * (1.0 / PI);

vec3 layerSum = diffuse + specular;

if (material.clearcoat > 0.0) {
vec3 coatN = normalize(material.clearcoatNormal);
vec3 coatSpecular = evaluateSpecularBRDF(coatN, v, l, vec3(0.04), material.clearcoatRoughness);
float coatF = fresnelSchlick(saturate(dot(v, coatN)), vec3(0.04)).r;
layerSum = mix(layerSum, coatSpecular, material.clearcoat * coatF);
}

if (max(max(material.sheenColor.r, material.sheenColor.g), material.sheenColor.b) > 0.0) {
float edge = pow(1.0 - NoV, 5.0);
vec3 sheen = material.sheenColor * edge * (1.0 - material.metallic);
layerSum += sheen;
}

vec3 transmitted = vec3(0.0);
if (material.transmission > 0.0) {
transmitted = sampleTransmissionApprox(n, v, material.roughness) * material.baseColor;
layerSum = mix(layerSum, transmitted, material.transmission * (1.0 - material.metallic));
}

return layerSum * lightColor * NoL * material.occlusion;
}

这段代码中 if 分支服务可读性,工程实现可以用材质变体、静态开关、动态分支或统一 uber shader 处理。关键约束是每个分支都要有明确禁用值:clearcoat 为 0 时顶层消失,sheenColor 为黑色时绒感层消失,transmission 为 0 时不采样透射路径。没有禁用值的层会增加贴图采样、ALU 和 IBL 查询,也会提高材质调试难度。

normal map 与 clearcoat normal map 要分开看。基础 normal map 改变底层漫反射、金属反射和普通镜面;clearcoatNormalTexture 只改变清漆层高光。车漆材质中,底层金属 flakes 可以有明显法线扰动,顶层清漆仍然保持平滑。若两层共用同一张强法线贴图,清漆高光会碎裂,车漆会失去顶层连续反射。

材质参数还要经过范围限制。roughness 接近 0 时会带来极窄高光和数值尖峰,通常需要设置最小值;transmission、clearcoat、metallic、occlusion 应夹到 [0, 1];normal map 解码后必须归一化;TBN 矩阵应处理非均匀缩放和 handedness。复杂 PBR 的很多错误在公式层面看不到,实际根源是资产数据进入 shader 前已经越界。

32.4 Material BRDF Evaluation Cost Control

复杂材质的成本来自四类路径:ALU 公式、texture fetch、IBL lookup 和 shader control flow。测试球只有一个物体时成本不明显;放入角色、车辆、玻璃建筑和布料场景后,每个像素的层数会乘上光源数量、阴影成本、透明排序和后处理成本。成本控制的目标是让材质外观按可见收益分级,而非让所有像素执行完整材质模型。

第一种控制方式是 LUT 和预积分。BRDF 中随 NoV、roughness 或 Fresnel 变化的半球积分可以预先存入 2D LUT;环境镜面反射可以预过滤到不同 mip;diffuse irradiance 可以用低频 cubemap 或球谐近似。这样 shader 用少量采样替代昂贵积分。代价是 LUT 和预过滤贴图必须和 BRDF 假设一致,GGX、Smith、roughness 映射或 Fresnel 参数变化后,旧 LUT 会带来系统性偏差。

第二种控制方式是贴图通道打包。metallic、roughness、AO、clearcoat、transmission 等标量可以合并到一张或少数几张纹理,降低绑定数量和采样次数。通道打包的判断标准是采样频率一致、UV 一致、颜色空间一致、压缩格式合适。把 sRGB 颜色和 linear 数据塞进同一张贴图会制造解码冲突;把需要高精度的 roughness 放入强压缩通道可能导致高光分段。

第三种控制方式是材质分级。近景 hero asset 可以启用 clearcoat normal、anisotropy、transmission blur 和高质量 IBL;中景材质保留 base D/G/F 与预过滤环境;远景或小屏幕占比物体使用更少贴图、更粗 mip、更少层数。分级依据应来自屏幕占比、材质是否透明、是否占据视觉焦点、是否参与反射和是否在强光下展示高光。

第四种控制方式是分支合并和变体边界。uber shader 便于统一材质系统,但所有功能都塞进一个动态 shader 后,寄存器压力、分支发散和编译时间都会上升。材质变体可以按 feature flag 拆分,例如 base、clearcoat、transparent、cloth、skin、anisotropic。拆分过细会带来 pipeline 数量和热更新成本;拆分过粗会让大量材质执行无效路径。比较合理的边界是把会引入新贴图、新 IBL 查询或透明排序的功能拆成变体,把单纯标量调节保留在同一变体。

第五种控制方式是光源路径分级。直接光下的 clearcoat、sheen 和 anisotropy 可以按主光完整评估,对低影响小灯或 clustered light 中的远光源使用简化项。IBL 路径下,anisotropy 很难按真实半球积分实时计算,常用 bent normal 或近似反射方向采样预过滤环境。这个近似要在材质文档中标注,因为它会影响拉丝金属在环境反射中的方向感。

性能排查时应把一帧拆成证据链:GPU profiler 中看 fragment time 和 texture bandwidth,frame capture 中看材质变体和绑定贴图,shader 编译统计中看指令数、寄存器和分支,画面中看高光、边缘反射和透明排序。若关闭 clearcoat 后帧耗时明显下降,瓶颈可能是新增 BRDF 评估或清漆法线采样;若关闭 transmission 后排序和 overdraw 改善,瓶颈可能在透明管线;若粗糙金属在环境光下代价高,瓶颈可能在 IBL 采样和 mip 访问。

下面的检查表可以用于一次材质成本复盘。

观察对象先看证据常见原因稳定处理
高光过宽且噪声明显roughness 贴图、mip、normal map数据贴图解码或 mip 选择错误固定 linear 读取并检查 roughness 范围
金属过黑prefiltered environment、BRDF LUT、baseColorIBL 缺失或 F0 混合错误先用白色环境验证镜面路径
车漆高光碎裂clearcoat normal、TBN清漆层误用底层强法线分离 base normal 与 coat normal
布料边缘过亮sheenColor、NoV、能量补偿sheen 层叠加过量使用层权重约束 base 能量
透明材质排序异常draw order、depth write、blend modetransmission 与 alpha coverage 混用区分表面存在性与透光比例
shader 变体爆炸pipeline cache、feature flags每个标量都生成变体只为资源路径变化生成变体

成本控制的收束标准是视觉收益可解释。保留某个层时,应能说明它改变了哪种可观察结果;删减某个层时,应能说明它在哪些距离、光照或材质类别下影响最小。复杂材质系统的稳定性来自这种明确边界。

32.5 不同材质在场景中的表现

同一颗测试球切换材质时,最先观察高光颜色、漫反射颜色、掠射角、环境反射和透射背景。材质差异主要靠能量路径区分,baseColor 只提供其中一部分外观信息;真正稳定的 PBR 外观来自能量路径差异。金属、塑料、玻璃、布料和皮肤在同一光照下呈现不同结果,原因分别落在 F0、diffuse 权重、transmission、sheen 和 subsurface 近似上。

金属的核心特征是有色镜面反射和低漫反射。金球在白色主光下的高光会带有金色,暗部依赖环境反射保留形体。roughness 低时,环境贴图反射清晰;roughness 高时,反射变宽并被预过滤 mip 模糊。若金属看起来像涂了黄色塑料,通常是 metallic 值未生效、F0 未从 baseColor 获取,或 diffuse 权重没有被 metallic 衰减。

塑料的核心特征是有色漫反射加白色或弱色镜面。红色塑料测试球正视角主要显示红色 diffuse,边缘和强光处出现接近白色的 Fresnel 高光。roughness 控制高光大小,baseColor 控制 diffuse 颜色,F0 常保持低值。若塑料高光被 baseColor 染得过重,metallic 混合或 specular color 参数可能被错误使用。

玻璃的核心特征是反射和透射同时存在。正视角可以看到背景透过材质,掠射角反射明显增强;roughness 越高,透射背景和反射都越模糊。薄玻璃材质通常不表达真实厚度折射,厚玻璃需要 volume、thickness、IOR 和折射路径近似。若透明球在 alpha 为 0 时完全消失,说明系统把 alpha coverage 当成 optical transmission 使用;这会破坏玻璃最关键的反射可见性。

布料的核心特征是柔和 diffuse、较弱普通镜面和掠射角 sheen。天鹅绒或粗布在正视角可能暗且低反射,边缘会出现带颜色的柔亮层。sheenRoughness 控制边缘亮度的宽度,sheenColor 控制微纤维反射颜色。若布料表现为光滑塑料,应检查 sheen 层是否启用、normal 是否过强、roughness 是否过低。

皮肤的核心特征是表面油脂镜面加浅层散射。真实皮肤材质通常需要 normal、roughness、specular、subsurface color、thickness 或 curvature 近似共同工作。正视角可以看到局部油脂高光,阴影边界应保留浅层散射带来的柔和过渡;耳廓、鼻翼和薄皮肤区域可加入 translucency 或 thickness 控制。若皮肤看起来像蜡,散射半径或透光强度过高;若看起来像粉末,镜面项或 Fresnel 贡献不足。

车漆能展示多层材质的完整路径。底层可能是有色 base 或金属 flakes,顶层 clearcoat 负责锐利、接近无色的反射。观察车漆时应同时看两个高光:底层高光受底材 roughness 和 flakes 影响,顶层高光受 clearcoatRoughness 和 clearcoatNormal 影响。两者重叠但来源不同,所以调试时要分别关闭 base specular 和 clearcoat。

这些材质可以放入同一套判断顺序。先把光照固定,用白色环境和单一主光排除照明差异;再把 normal map 关闭,检查基础 BRDF 是否正确;随后逐层启用 clearcoat、sheen、transmission、anisotropy 或 subsurface 近似;最后恢复真实贴图和 HDR 环境。每一步只改变一个变量,画面差异才能回到具体管线对象。

最小自检任务

给定同一颗测试球、同一盏白色方向光、同一张 HDR 环境贴图和同一张 normal map,场景中出现三个问题:金属球暗部接近纯黑,玻璃球正视角透明但边缘没有反射,布料球边缘像塑料高光一样尖锐。请按本章的检查顺序判断每个问题最可能来自哪条材质路径,并给出最小排查步骤。

答案要点

金属球暗部接近纯黑,应先检查 IBL 镜面路径。金属的 diffuse 权重很低,暗部主要依赖 prefiltered environment 和 BRDF LUT。如果直接光高光正常、环境反射缺失,优先验证反射向量、prefiltered cubemap、roughness mip、BRDF LUT 和 baseColor 到 F0 的 metallic 混合。

玻璃球正视角透明但边缘没有反射,应检查 transmission 与 Fresnel 的关系。物理透明表面仍然有表面反射,掠射角反射应增强。最小步骤是把 transmissionFactor 保持不变,单独输出 Fresnel 项或 specular 项;若边缘仍无反射,再检查 alpha coverage 是否替代了 optical transmission,以及 transparent pass 是否保留 specular 评估。

布料球边缘像塑料高光一样尖锐,应检查 sheen 层和 roughness。布料边缘亮度应来自较柔的微纤维 sheen,普通 specular 过强或 roughness 过低会产生塑料感。最小步骤是关闭普通 specular 的强度观察边缘,再单独输出 sheenColor 与 sheenRoughness;若 sheen 未生效,检查材质扩展、贴图通道和能量补偿。

完整排查顺序是:固定光照和环境;关闭 normal map 验证基础 BRDF;检查金属 F0 与 IBL;检查玻璃 Fresnel、transmission 和 alpha coverage 边界;检查布料 sheen 与普通 specular 的分工;最后恢复贴图并观察同一角度下的差异是否可复现。

本章知识点总结

  • 微表面:宏观高光来自大量微面法线的统计分布,roughness 通过分布形状改变高光宽度和拖尾。
  • D 项:法线分布函数决定朝向半程向量的微面比例,是高光集中程度的主要来源。
  • G 项:几何项表达微面遮蔽和遮挡,会影响暗边、掠射角和粗糙材质的能量稳定性。
  • F 项:Fresnel 项控制视角相关反射,电介质正视角反射低,掠射角反射增强。
  • 金属路径:金属使用有色镜面反射并压低漫反射,环境反射质量直接影响暗部形体。
  • 吸收散射:吸收改变波长能量,散射改变出射方向和位置,实时材质用参数和贴图近似这些路径。
  • 透射路径:transmission 表达光穿过表面的比例,玻璃透明仍需要保留表面反射和 Fresnel 变化。
  • 清漆层:clearcoat 是覆盖在基础材质上的微表面反射层,常用独立 roughness 和 normal 控制顶层高光。
  • 绒感层:sheen 表达微纤维材质的掠射角柔亮,应和普通塑料镜面高光区分。
  • 各向异性:anisotropy 通过 tangent / bitangent 空间拉伸 NDF,让高光沿材质纹理方向展开。
  • IBL 近似:实时环境光通常依赖 irradiance、prefiltered radiance 和 BRDF LUT 近似半球积分。
  • 通道校验:颜色贴图和数据贴图的颜色空间、通道打包和取值范围会直接改变 BRDF 输入。
  • 成本控制:复杂材质成本来自公式、采样、IBL 和分支,应按可见收益决定 LUT、分级和变体边界。
  • 排查顺序:复杂材质调试应先固定光照,再关闭法线,随后逐层启用材质功能,最后恢复真实贴图。