跳转到内容

基于物理的渲染材质(PBR)

Author: Charley

PBR(Physically Based Rendering,基于物理的渲染)材质是LayaAir引擎中最常用的高品质材质类型。它通过模拟自然界的物理光照规律,使3D模型呈现出更加真实的质感,能够准确还原金属、木材、塑料、皮革等各种不同材料的外观特征。

PBR是一种基于物理规律的着色模型,其核心思想是通过物理上合理的方式来描述光线与材质表面的交互。与传统的光照模型(如Blinn-Phong)相比,PBR材质的优势在于:

  • 物理正确性:遵循能量守恒定律,光照效果更加真实;
  • 直观的参数:使用金属度、粗糙度等直观参数描述材质,美术调参更加方便;
  • 环境一致性:材质在不同的光照环境下都能呈现合理的效果。

在LayaAir引擎中,PBR材质的类继承关系为:

Material → PBRMaterial → PBRStandardMaterial
  • PBRMaterial:PBR材质的基类,包含了PBR材质的通用属性(反照率、法线、遮蔽、自发光等);
  • PBRStandardMaterial:PBR标准材质,在 PBRMaterial 基础上增加了金属度工作流相关属性。

在IDE中创建材质并选择PBR(Standard)Shader时,使用的就是 PBRStandardMaterial

反照率描述了材质表面的基础颜色,即物体本身的颜色(不包含光照信息)。

反照率颜色定义了材质表面的固有颜色,是一个RGBA值。

(图2-1)

反照率贴图用于提供逐像素的颜色信息,使材质表面呈现更丰富的细节。贴图颜色会与反照率颜色相乘。

(图2-2)

2.3 纹理平铺和偏移(tilingOffset)

Section titled “2.3 纹理平铺和偏移(tilingOffset)”

控制纹理在模型表面的重复次数和偏移量。类型为 Vector4,其中:

  • X、Y分量:纹理在U、V方向的重复次数(Tiling)
  • Z、W分量:纹理在U、V方向的偏移量(Offset)

金属度和光滑度是PBR材质的核心参数,它们共同决定了材质对光线的反射方式。

金属度描述物体表面在多大程度上像金属。取值范围为0到1:

说明
0非金属(绝缘体),如木头、塑料、皮革等
1纯金属,如金、银、铁等
0~1过渡值,用于模拟带有氧化层或涂层的金属

(图3-1)

光滑度描述物体表面的光滑程度。取值范围为0到1:

说明
0完全粗糙,漫反射为主,如未打磨的石头
1完全光滑,镜面反射为主,如镜子

(图3-2)

注意:在某些PBR工作流中,使用”粗糙度”(Roughness)代替光滑度,两者是互补关系:粗糙度 = 1 - 光滑度

3.3 金属光滑度贴图(metallicGlossTexture)

Section titled “3.3 金属光滑度贴图(metallicGlossTexture)”

金属光滑度贴图可以在一张纹理中同时提供金属度和光滑度信息,实现逐像素的精确控制。

3.4 光滑度数据源(smoothnessSource)

Section titled “3.4 光滑度数据源(smoothnessSource)”

smoothnessSource 属性控制光滑度数据的来源,类型为 PBRMetallicSmoothnessSource

说明
0从金属光滑度贴图的Alpha通道读取
1从反照率贴图的Alpha通道读取

法线贴图通过修改表面法线方向来模拟凹凸细节,而无需增加实际的几何面数。它可以让低面数模型呈现出丰富的表面细节效果。

(图4-1)

4.2 法线贴图缩放系数(normalTextureScale)

Section titled “4.2 法线贴图缩放系数(normalTextureScale)”

控制法线贴图的影响强度。值越大,凹凸效果越明显;值为0时法线贴图不生效。

遮蔽贴图(也称AO贴图,Ambient Occlusion)用于模拟环境光在缝隙、角落等位置的遮蔽效果,使这些区域看起来更暗,增强立体感和真实感。 (图5-1)

5.2 遮蔽贴图强度(occlusionTextureStrength)

Section titled “5.2 遮蔽贴图强度(occlusionTextureStrength)”

控制遮蔽效果的强度,取值范围为0到1。值为1时遮蔽效果最强,值为0时无遮蔽效果。

自发光效果使材质看起来像是自身在发光,常用于LED屏幕、霓虹灯、岩浆等效果。自发光不会对周围物体产生照明效果。

通过设置 enableEmissiontrue 来开启自发光功能。

设置自发光的颜色。

自发光贴图可以精确控制模型不同区域的发光效果和颜色。

6.4 自发光强度(emissionIntensity)

Section titled “6.4 自发光强度(emissionIntensity)”

控制自发光的亮度强度。

各向异性反射用于模拟在特定方向上具有不同反射特性的材质,如拉丝金属、丝绸、光盘等。

7.1 开启各向异性(anisotropyEnable)

Section titled “7.1 开启各向异性(anisotropyEnable)”

设置 anisotropyEnabletrue 开启各向异性功能。

属性类型说明
anisotropynumber各向异性强度
anisotropyRotationnumber各向异性在切线空间中的旋转角度
anisotropyTextureTexture2D各向异性强度贴图

(图7-1)

清漆层用于模拟表面有透明涂层的材质,如汽车漆面、漆器、包装薄膜等。

设置 clearCoatEnabletrue 开启清漆层。

属性类型说明
clearCoatnumber清漆层强度
clearCoatRoughnessnumber清漆层粗糙度
clearCoatTextureBaseTexture清漆层强度贴图
clearCoatRoughnessTextureBaseTexture清漆层粗糙度贴图
clearCoatNormalTextureBaseTexture清漆层法线贴图

细节贴图用于在近距离观察时为材质添加更多的表面细节:

属性类型说明
detailAlbedoTextureBaseTexture细节反照率贴图
detailNormalTextureBaseTexture细节法线贴图
detailNormalScalenumber细节法线缩放系数
detailTilingOffsetVector4细节贴图的平铺和偏移

视差贴图通过偏移纹理坐标来模拟更强的深度效果:

属性类型说明
parallaxTextureBaseTexture视差贴图
parallaxTextureScalenumber视差贴图缩放系数

PBR材质支持以下渲染模式,通过 renderMode 属性设置:

渲染模式说明
Opaque0不透明渲染,默认模式,性能最优
Cutout1Alpha裁剪,根据Alpha阈值决定像素是否可见
Fade2透明混合,游戏中经常使用的透明
Transparent3透明混合,物理上看似合理的透明

PBR材质还提供了渲染质量设置(PBRRenderQuality 枚举),可在高质量和低质量之间切换,以适应不同平台的性能需求。

属性类型说明
enableVertexColorboolean是否支持顶点色,开启后可叠加网格的顶点颜色
// 创建PBR标准材质
let pbrMat = new Laya.PBRStandardMaterial();
// 设置反照率
pbrMat.albedoColor = new Laya.Color(0.8, 0.2, 0.2, 1.0);
// 设置金属度和光滑度
pbrMat.metallic = 0.9;
pbrMat.smoothness = 0.7;
// 加载反照率贴图
Laya.loader.load("res/texture/albedo.png").then((tex: Laya.Texture2D) => {
pbrMat.albedoTexture = tex;
});
// 加载法线贴图
Laya.loader.load("res/texture/normal.png").then((tex: Laya.Texture2D) => {
pbrMat.normalTexture = tex;
pbrMat.normalTextureScale = 1.0;
});
// 设置渲染模式为不透明
pbrMat.renderMode = Laya.PBRRenderMode.Opaque;
// 应用到模型
let meshRenderer = sprite3D.getComponent(Laya.MeshRenderer);
meshRenderer.sharedMaterial = pbrMat;
let emissiveMat = new Laya.PBRStandardMaterial();
emissiveMat.albedoColor = new Laya.Color(0.1, 0.1, 0.1, 1.0);
emissiveMat.metallic = 0.0;
emissiveMat.smoothness = 0.5;
// 开启自发光
emissiveMat.enableEmission = true;
emissiveMat.emissionColor = new Laya.Color(0, 1, 0.5, 1);
emissiveMat.emissionIntensity = 2.0;
meshRenderer.sharedMaterial = emissiveMat;
let anisotropicMat = new Laya.PBRStandardMaterial();
anisotropicMat.albedoColor = new Laya.Color(0.8, 0.8, 0.8, 1.0);
anisotropicMat.metallic = 1.0;
anisotropicMat.smoothness = 0.8;
// 开启各向异性
anisotropicMat.anisotropyEnable = true;
anisotropicMat.anisotropy = 0.8;
anisotropicMat.anisotropyRotation = 0.0;
meshRenderer.sharedMaterial = anisotropicMat;