Babylon.js 材质系统 #
材质概述 #
材质决定了 3D 物体的外观,包括颜色、纹理、光泽度、透明度等属性。Babylon.js 提供了多种材质类型,从简单的标准材质到复杂的 PBR 材质。
text
┌─────────────────────────────────────────────────────────────┐
│ Babylon.js 材质类型 │
├─────────────────────────────────────────────────────────────┤
│ │
│ StandardMaterial ─── 标准材质 │
│ - 最常用的材质类型 │
│ - 支持多种贴图 │
│ - 适合大多数场景 │
│ │
│ PBRMaterial ──────── PBR 材质 │
│ - 物理真实渲染 │
│ - 金属/粗糙度工作流 │
│ - 高质量渲染效果 │
│ │
│ NodeMaterial ─────── 节点材质 │
│ - 可视化材质编辑 │
│ - 自定义着色器 │
│ - 高度灵活 │
│ │
│ ShaderMaterial ───── 着色器材质 │
│ - 自定义 GLSL 代码 │
│ - 完全控制渲染 │
│ - 高级用户使用 │
│ │
└─────────────────────────────────────────────────────────────┘
StandardMaterial 标准材质 #
基本创建 #
javascript
const material = new BABYLON.StandardMaterial('material', scene);
// 应用到网格
mesh.material = material;
基础颜色 #
javascript
// 漫反射颜色(基础颜色)
material.diffuseColor = new BABYLON.Color3(1, 0, 0); // 红色
// 高光颜色
material.specularColor = new BABYLON.Color3(1, 1, 1);
// 发光颜色
material.emissiveColor = new BABYLON.Color3(0.2, 0.2, 0);
// 环境颜色
material.ambientColor = new BABYLON.Color3(0.3, 0.3, 0.3);
颜色属性说明 #
text
┌─────────────────────────────────────────────────────────────┐
│ 标准材质颜色属性 │
├─────────────────────────────────────────────────────────────┤
│ │
│ diffuseColor(漫反射颜色) │
│ - 物体的基础颜色 │
│ - 受光源影响 │
│ │
│ specularColor(高光颜色) │
│ - 光泽表面的高光颜色 │
│ - 配合 specularPower 使用 │
│ │
│ emissiveColor(自发光颜色) │
│ - 物体自身发出的光 │
│ - 不受光源影响 │
│ │
│ ambientColor(环境光颜色) │
│ - 环境光照射下的颜色 │
│ - 增加暗部细节 │
│ │
└─────────────────────────────────────────────────────────────┘
光泽度设置 #
javascript
// 高光强度
material.specularPower = 32; // 值越大,高光越集中
// 高光颜色
material.specularColor = new BABYLON.Color3(0.5, 0.5, 0.5);
透明度 #
javascript
// 透明度
material.alpha = 0.5; // 0 = 完全透明,1 = 完全不透明
// 透明模式
material.transparencyMode = BABYLON.Material.MATERIAL_ALPHABLEND;
// 可选模式:
// MATERIAL_OPAQUE - 不透明
// MATERIAL_ALPHATEST - Alpha 测试
// MATERIAL_ALPHABLEND - Alpha 混合
纹理贴图 #
漫反射贴图 #
javascript
const material = new BABYLON.StandardMaterial('mat', scene);
// 加载漫反射贴图
material.diffuseTexture = new BABYLON.Texture('/textures/diffuse.jpg', scene);
// 贴图属性
material.diffuseTexture.uScale = 1; // U 方向缩放
material.diffuseTexture.vScale = 1; // V 方向缩放
material.diffuseTexture.uOffset = 0; // U 方向偏移
material.diffuseTexture.vOffset = 0; // V 方向偏移
贴图类型 #
text
┌─────────────────────────────────────────────────────────────┐
│ 标准材质贴图类型 │
├─────────────────────────────────────────────────────────────┤
│ │
│ diffuseTexture ──── 漫反射贴图 │
│ - 物体的基础颜色纹理 │
│ │
│ normalTexture ───── 法线贴图 │
│ - 增加表面细节 │
│ - 模拟凹凸效果 │
│ │
│ specularTexture ─── 高光贴图 │
│ - 控制高光分布 │
│ │
│ bumpTexture ─────── 凹凸贴图 │
│ - 简单的表面凹凸效果 │
│ │
│ opacityTexture ──── 透明贴图 │
│ - 控制透明度分布 │
│ │
│ emissiveTexture ─── 自发光贴图 │
│ - 自发光区域纹理 │
│ │
│ ambientTexture ──── 环境贴图 │
│ - 环境光照纹理 │
│ │
└─────────────────────────────────────────────────────────────┘
法线贴图 #
javascript
// 加载法线贴图
material.normalTexture = new BABYLON.Texture('/textures/normal.jpg', scene);
// 法线强度
material.normalTexture.level = 1.0;
高光贴图 #
javascript
// 加载高光贴图
material.specularTexture = new BABYLON.Texture('/textures/specular.jpg', scene);
// 高光贴图影响颜色
material.useSpecularOverAlpha = true;
透明贴图 #
javascript
// 加载透明贴图
material.opacityTexture = new BABYLON.Texture('/textures/opacity.jpg', scene);
// 设置透明模式
material.transparencyMode = BABYLON.Material.MATERIAL_ALPHABLEND;
material.alpha = 1.0;
纹理坐标 #
javascript
// UV 重复
material.diffuseTexture.wrapU = BABYLON.Texture.WRAP_ADDRESSMODE;
material.diffuseTexture.wrapV = BABYLON.Texture.WRAP_ADDRESSMODE;
// 可选模式:
// CLAMP_ADDRESSMODE - 边缘拉伸
// WRAP_ADDRESSMODE - 重复
// MIRROR_ADDRESSMODE - 镜像重复
// UV 动画
scene.onBeforeRenderObservable.add(() => {
material.diffuseTexture.uOffset += 0.001;
material.diffuseTexture.vOffset += 0.001;
});
PBRMaterial PBR 材质 #
PBR(Physically Based Rendering)材质基于物理渲染,能产生更真实的效果。
基本创建 #
javascript
const pbrMaterial = new BABYLON.PBRMaterial('pbr', scene);
mesh.material = pbrMaterial;
金属/粗糙度工作流 #
javascript
// 基础颜色
pbrMaterial.albedoColor = new BABYLON.Color3(1, 0.8, 0.6);
// 金属度(0 = 非金属,1 = 金属)
pbrMaterial.metallic = 0.9;
// 粗糙度(0 = 光滑,1 = 粗糙)
pbrMaterial.roughness = 0.2;
PBR 材质属性 #
text
┌─────────────────────────────────────────────────────────────┐
│ PBR 材质属性 │
├─────────────────────────────────────────────────────────────┤
│ │
│ albedoColor/Texture ─ 基础颜色 │
│ - 物体的基础颜色 │
│ │
│ metallic ─────────── 金属度 │
│ - 0: 非金属(电介质) │
│ - 1: 金属 │
│ │
│ roughness ────────── 粗糙度 │
│ - 0: 完全光滑(镜面反射) │
│ - 1: 完全粗糙(漫反射) │
│ │
│ reflectivityColor ─ 反射颜色 │
│ - 非金属的反射率 │
│ │
│ microSurface ─────── 微表面 │
│ - 表面光滑度 │
│ │
└─────────────────────────────────────────────────────────────┘
PBR 贴图 #
javascript
// 基础颜色贴图
pbrMaterial.albedoTexture = new BABYLON.Texture('/textures/albedo.jpg', scene);
// 金属粗糙度贴图
pbrMaterial.metallicTexture = new BABYLON.Texture('/textures/metallic.jpg', scene);
// 设置贴图通道
pbrMaterial.useMetallnessFromMetallicTextureAlpha = false;
pbrMaterial.useRoughnessFromMetallicTextureAlpha = false;
pbrMaterial.metallicTextureMetallicChannel = 2; // 蓝色通道
pbrMaterial.metallicTextureRoughnessChannel = 1; // 绿色通道
// 法线贴图
pbrMaterial.normalTexture = new BABYLON.Texture('/textures/normal.jpg', scene);
// 环境遮蔽贴图
pbrMaterial.ambientTexture = new BABYLON.Texture('/textures/ao.jpg', scene);
pbrMaterial.ambientTextureStrength = 1.0;
// 自发光贴图
pbrMaterial.emissiveTexture = new BABYLON.Texture('/textures/emissive.jpg', scene);
pbrMaterial.emissiveColor = new BABYLON.Color3(1, 1, 1);
环境贴图 #
javascript
// 加载 HDR 环境贴图
const hdrTexture = new BABYLON.CubeTexture.CreateFromPrefilteredData(
'/textures/environment.env',
scene
);
// 设置环境贴图
scene.environmentTexture = hdrTexture;
scene.environmentIntensity = 0.5;
// PBR 材质会自动使用环境贴图
常见材质预设 #
javascript
// 金属材质
function createMetalMaterial(scene, color) {
const mat = new BABYLON.PBRMaterial('metal', scene);
mat.albedoColor = color;
mat.metallic = 1.0;
mat.roughness = 0.2;
return mat;
}
// 塑料材质
function createPlasticMaterial(scene, color) {
const mat = new BABYLON.PBRMaterial('plastic', scene);
mat.albedoColor = color;
mat.metallic = 0;
mat.roughness = 0.5;
return mat;
}
// 玻璃材质
function createGlassMaterial(scene) {
const mat = new BABYLON.PBRMaterial('glass', scene);
mat.albedoColor = new BABYLON.Color3(1, 1, 1);
mat.metallic = 0;
mat.roughness = 0;
mat.alpha = 0.5;
mat.transparencyMode = BABYLON.Material.MATERIAL_ALPHABLEND;
return mat;
}
// 金色材质
const gold = createMetalMaterial(scene, new BABYLON.Color3(1, 0.765, 0.336));
gold.roughness = 0.3;
// 银色材质
const silver = createMetalMaterial(scene, new BABYLON.Color3(0.972, 0.96, 0.915));
silver.roughness = 0.3;
// 铜色材质
const copper = createMetalMaterial(scene, new BABYLON.Color3(0.955, 0.637, 0.538));
copper.roughness = 0.4;
NodeMaterial 节点材质 #
NodeMaterial 允许通过可视化节点编辑器创建材质。
基本使用 #
javascript
// 从 JSON 创建节点材质
const nodeMaterial = new BABYLON.NodeMaterial('nodeMat', scene);
// 加载材质定义
await nodeMaterial.loadAsync('/materials/material.json');
// 构建材质
nodeMaterial.build();
// 应用到网格
mesh.material = nodeMaterial;
在线编辑器 #
text
Node Material Editor 在线地址:
https://nme.babylonjs.com/
代码创建节点材质 #
javascript
const nodeMaterial = new BABYLON.NodeMaterial('nodeMat', scene);
// 创建节点
const position = new BABYLON.InputBlock('position');
position.setAsAttribute('position');
const world = new BABYLON.InputBlock('world');
world.setAsSystemValue(BABYLON.NodeMaterialSystemValues.World);
// 连接节点
const worldPos = new BABYLON.TransformBlock('worldPos');
worldPos.connectTo(position, worldPos);
// 设置输出
const fragmentOutput = new BABYLON.FragmentOutputBlock('fragmentOutput');
// ... 连接更多节点
// 构建材质
nodeMaterial.build();
ShaderMaterial 着色器材质 #
ShaderMaterial 允许编写自定义 GLSL 着色器。
基本创建 #
javascript
const shaderMaterial = new BABYLON.ShaderMaterial(
'shader',
scene,
{
vertexSource: vertexShaderCode,
fragmentSource: fragmentShaderCode,
},
{
attributes: ['position', 'normal', 'uv'],
uniforms: ['world', 'worldView', 'worldViewProjection', 'view', 'projection']
}
);
mesh.material = shaderMaterial;
顶点着色器示例 #
glsl
// 顶点着色器
precision highp float;
attribute vec3 position;
attribute vec3 normal;
attribute vec2 uv;
uniform mat4 world;
uniform mat4 worldViewProjection;
varying vec3 vNormal;
varying vec2 vUV;
void main() {
gl_Position = worldViewProjection * vec4(position, 1.0);
vNormal = normalize((world * vec4(normal, 0.0)).xyz);
vUV = uv;
}
片段着色器示例 #
glsl
// 片段着色器
precision highp float;
varying vec3 vNormal;
varying vec2 vUV;
uniform vec3 lightDirection;
uniform vec3 baseColor;
void main() {
float light = max(dot(vNormal, normalize(lightDirection)), 0.0);
vec3 color = baseColor * (0.3 + 0.7 * light);
gl_FragColor = vec4(color, 1.0);
}
设置 Uniform #
javascript
// 设置 uniform 值
shaderMaterial.setVector3('lightDirection', new BABYLON.Vector3(1, 1, 1));
shaderMaterial.setColor3('baseColor', new BABYLON.Color3(1, 0, 0));
// 设置纹理
shaderMaterial.setTexture('textureSampler', new BABYLON.Texture('/texture.jpg', scene));
// 动态更新
scene.onBeforeRenderObservable.add(() => {
shaderMaterial.setFloat('time', performance.now() * 0.001);
});
材质高级特性 #
双面渲染 #
javascript
material.backFaceCulling = false; // 禁用背面剔除
material.doubleSided = true; // 双面材质
线框模式 #
javascript
material.wireframe = true;
点模式 #
javascript
material.pointsCloud = true;
material.pointSize = 3;
材质混合 #
javascript
// 多材质混合
const multiMat = new BABYLON.MultiMaterial('multi', scene);
multiMat.subMaterials.push(material1);
multiMat.subMaterials.push(material2);
// 应用到网格
mesh.material = multiMat;
mesh.subMeshes = [];
mesh.subMeshes.push(new BABYLON.SubMesh(0, 0, verticesCount, 0, indicesCount / 2, mesh));
mesh.subMeshes.push(new BABYLON.SubMesh(1, 0, verticesCount, indicesCount / 2, indicesCount / 2, mesh));
材质动画 #
javascript
// 颜色动画
const colorAnimation = new BABYLON.Animation(
'colorAnim',
'diffuseColor',
30,
BABYLON.Animation.ANIMATIONTYPE_COLOR3,
BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE
);
colorAnimation.setKeys([
{ frame: 0, value: new BABYLON.Color3(1, 0, 0) },
{ frame: 30, value: new BABYLON.Color3(0, 1, 0) },
{ frame: 60, value: new BABYLON.Color3(0, 0, 1) },
{ frame: 90, value: new BABYLON.Color3(1, 0, 0) }
]);
material.animations.push(colorAnimation);
scene.beginAnimation(material, 0, 90, true);
// 透明度动画
const alphaAnimation = new BABYLON.Animation(
'alphaAnim',
'alpha',
30,
BABYLON.Animation.ANIMATIONTYPE_FLOAT,
BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE
);
alphaAnimation.setKeys([
{ frame: 0, value: 1 },
{ frame: 30, value: 0 },
{ frame: 60, value: 1 }
]);
material.animations.push(alphaAnimation);
scene.beginAnimation(material, 0, 60, true);
材质优化 #
材质冻结 #
javascript
// 冻结材质(提高性能)
material.freeze();
// 解冻
material.unfreeze();
材质实例 #
javascript
// 创建材质实例(共享基础材质)
const baseMaterial = new BABYLON.StandardMaterial('base', scene);
// 使用材质实例
const instance1 = baseMaterial.clone('instance1');
instance1.diffuseColor = new BABYLON.Color3(1, 0, 0);
const instance2 = baseMaterial.clone('instance2');
instance2.diffuseColor = new BABYLON.Color3(0, 1, 0);
纹理优化 #
javascript
// 设置纹理采样
texture.samplingMode = BABYLON.Texture.TRILINEAR_SAMPLINGMODE;
// 可选模式:
// NEAREST_SAMPLINGMODE - 最近邻
// BILINEAR_SAMPLINGMODE - 双线性
// TRILINEAR_SAMPLINGMODE - 三线性(推荐)
// 纹理压缩
texture.updateSamplingMode(BABYLON.Texture.TRILINEAR_SAMPLINGMODE);
实战:材质库 #
javascript
class MaterialLibrary {
constructor(scene) {
this.scene = scene;
this.materials = {};
this.init();
}
init() {
this.createBasicMaterials();
this.createPBRMaterials();
}
createBasicMaterials() {
// 红色材质
this.materials.red = new BABYLON.StandardMaterial('red', this.scene);
this.materials.red.diffuseColor = new BABYLON.Color3(1, 0, 0);
// 绿色材质
this.materials.green = new BABYLON.StandardMaterial('green', this.scene);
this.materials.green.diffuseColor = new BABYLON.Color3(0, 1, 0);
// 蓝色材质
this.materials.blue = new BABYLON.StandardMaterial('blue', this.scene);
this.materials.blue.diffuseColor = new BABYLON.Color3(0, 0, 1);
// 白色材质
this.materials.white = new BABYLON.StandardMaterial('white', this.scene);
this.materials.white.diffuseColor = new BABYLON.Color3(1, 1, 1);
}
createPBRMaterials() {
// 金属材质
this.materials.gold = new BABYLON.PBRMaterial('gold', this.scene);
this.materials.gold.albedoColor = new BABYLON.Color3(1, 0.765, 0.336);
this.materials.gold.metallic = 1.0;
this.materials.gold.roughness = 0.3;
this.materials.silver = new BABYLON.PBRMaterial('silver', this.scene);
this.materials.silver.albedoColor = new BABYLON.Color3(0.972, 0.96, 0.915);
this.materials.silver.metallic = 1.0;
this.materials.silver.roughness = 0.2;
// 玻璃材质
this.materials.glass = new BABYLON.PBRMaterial('glass', this.scene);
this.materials.glass.albedoColor = new BABYLON.Color3(1, 1, 1);
this.materials.glass.metallic = 0;
this.materials.glass.roughness = 0;
this.materials.glass.alpha = 0.5;
this.materials.glass.transparencyMode = BABYLON.Material.MATERIAL_ALPHABLEND;
// 塑料材质
this.materials.plastic = new BABYLON.PBRMaterial('plastic', this.scene);
this.materials.plastic.albedoColor = new BABYLON.Color3(0.8, 0.2, 0.2);
this.materials.plastic.metallic = 0;
this.materials.plastic.roughness = 0.5;
}
get(name) {
return this.materials[name] || this.materials.white;
}
createCustom(name, options) {
const mat = new BABYLON.PBRMaterial(name, this.scene);
if (options.color) {
mat.albedoColor = options.color;
}
if (options.metallic !== undefined) {
mat.metallic = options.metallic;
}
if (options.roughness !== undefined) {
mat.roughness = options.roughness;
}
if (options.alpha !== undefined) {
mat.alpha = options.alpha;
mat.transparencyMode = BABYLON.Material.MATERIAL_ALPHABLEND;
}
this.materials[name] = mat;
return mat;
}
}
// 使用
const matLib = new MaterialLibrary(scene);
box.material = matLib.get('gold');
sphere.material = matLib.createCustom('custom', {
color: new BABYLON.Color3(0.5, 0.8, 0.3),
metallic: 0.5,
roughness: 0.4
});
下一步 #
现在你已经掌握了材质系统,接下来学习 网格几何体,了解如何创建和操作 3D 物体!
最后更新:2026-03-29