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