Skip to content

BabylonJS - 材质

材质(Material)定义了网格(mesh)的表面外观。它们决定了光线如何与物体交互,控制其颜色、纹理、光泽度、透明度和其他视觉属性。应用不同的材质可以使同一个网格看起来像木头、金属、塑料、玻璃或任何其他可以想象到的东西。

Babylon.js 提供了几种类型的材质,其中最重要的是用于通用目的的 StandardMaterial(标准材质)和用于实现逼真效果的 PBRMaterial(基于物理的渲染材质)。

标准材质(BABYLON.StandardMaterial)

Section titled “标准材质(BABYLON.StandardMaterial)”

StandardMaterial 是一种基于传统 Blinn-Phong 光照模型的通用材质。它相对易于使用且性能良好。您将其分配给网格的 material 属性。

import * as BABYLON from '@babylonjs/core';
// Assuming 'scene' and 'myMesh' are defined
// 假设 'scene' 和 'myMesh' 已经定义
const myMaterial = new BABYLON.StandardMaterial("myStdMat", scene);
// --- Common Properties ---
// --- 常用属性 ---
// Color
// 颜色
myMaterial.diffuseColor = new BABYLON.Color3(1, 0, 0); // Red base color
// 红色基础颜色
// myMaterial.ambientColor = new BABYLON.Color3(0.1, 0.1, 0.1); // Color in ambient light
// 环境光下的颜色
myMaterial.specularColor = new BABYLON.Color3(1, 1, 1); // Color of highlights (white is common)
// 高光的颜色(白色很常见)
myMaterial.emissiveColor = new BABYLON.Color3(0, 0.1, 0); // Color the object emits itself (glow)
// 物体自身发出的颜色(辉光)
// Texture (overrides diffuseColor if set)
// 纹理(如果设置,则覆盖 diffuseColor)
// myMaterial.diffuseTexture = new BABYLON.Texture("textures/wood.jpg", scene);
// Shininess
// 光泽度
myMaterial.specularPower = 64; // Higher values = smaller, sharper highlights
// 值越高 = 高光越小、越锐利
// Transparency
// 透明度
myMaterial.alpha = 0.8; // 1.0 is fully opaque, 0.0 is fully transparent
// 1.0 表示完全不透明,0.0 表示完全透明
// Wireframe
// 线框模式
// myMaterial.wireframe = true; // Show mesh edges instead of surfaces
// 显示网格边缘而非表面
// Backface Culling (performance optimization, hides back faces)
// 背面剔除(性能优化,隐藏背面)
// myMaterial.backFaceCulling = false; // Set to false for planes or non-closed meshes
// 对于平面或非封闭网格,设置为 false
// Apply the material to the mesh
// 将材质应用到网格
myMesh.material = myMaterial;

StandardMaterial 支持各种纹理贴图以添加细节:

  • diffuseTexture:主颜色/图案纹理。
  • ambientTexture:在环境光下添加颜色细节。
  • specularTexture:按像素控制镜面高光的颜色/强度。
  • emissiveTexture:定义发光区域。
  • opacityTexture:按像素控制透明度(通常是灰度)。
  • bumpTexture:模拟表面细节(法线贴图),影响光照。
  • reflectionTexture:添加反射(通常是 CubeTexture 或 MirrorTexture)。
  • refractionTexture:模拟光线穿过透明材质(如玻璃)时的弯曲(需要 ReflectionProbe 或 CubeTexture)。

PBR 材质(Physically Based Rendering - 基于物理的渲染)

Section titled “PBR 材质(Physically Based Rendering - 基于物理的渲染)”

PBR 材质旨在模拟光线在现实世界中的行为,从而在不同光照条件下产生更逼真的视觉效果。它们是现代高保真图形推荐的方法。Babylon.js 主要使用金属度-粗糙度工作流(PBRMetallicRoughnessMaterial),但也支持镜面反射度-光泽度工作流(PBRSpecularGlossinessMaterial)。PBRMaterial 是一个基类,允许更复杂的设置。

关键 PBR 概念(金属度-粗糙度):

  • baseColor:材质的底层颜色(类似于漫反射颜色)。
  • metallic:表面“金属感”的程度(非金属/电介质为 0,金属为 1)。控制反射行为。
  • roughness:表面粗糙或光滑的程度(完全光滑/镜面为 0,非常粗糙/漫反射为 1)。影响高光锐度和反射清晰度。
  • 基于图像的光照(Image-Based Lighting - IBL):PBR 严重依赖 scene.environmentTexture(通常是 .env 或 .hdr 的 CubeTexture)来获得逼真的环境光照和反射。
// Create a PBR Metallic-Roughness material
// 创建一个 PBR 金属度-粗糙度材质
const pbrMaterial = new BABYLON.PBRMetallicRoughnessMaterial("myPBRMat", scene);
// Base Color
// 基础颜色
pbrMaterial.baseColor = new BABYLON.Color3(0.8, 0.8, 0.8); // Light gray
// 浅灰色
// Or use a texture
// 或者使用纹理
// pbrMaterial.baseTexture = new BABYLON.Texture("textures/metal_basecolor.png", scene);
// Metallic
// 金属度
pbrMaterial.metallic = 0.9; // Mostly metallic
// 主要为金属
// Roughness
// 粗糙度
pbrMaterial.roughness = 0.2; // Quite smooth
// 相当光滑
// Make sure scene has an environment texture for realistic reflections!
// 确保场景有环境纹理以获得逼真的反射!
// scene.environmentTexture = BABYLON.CubeTexture.CreateFromPrefilteredData("textures/environment.env", scene);
// Apply to mesh
// 应用到网格
myMesh.material = pbrMaterial;

PBR 材质使用特定的纹理贴图:

  • baseTexture:提供基础颜色。
  • metallicRoughnessTexture:通常将金属度(例如,蓝色通道)和粗糙度(例如,绿色通道)打包到一个纹理中以提高效率。
  • normalTexture:标准的法线贴图,用于表面细节。
  • ambientOcclusionTexture (或 occlusionTexture):添加细微的接触阴影。
  • emissiveTexture:定义发光区域。

菲涅尔效应(Fresnel effect)描述了反射率如何根据视角变化。表面在掠射角(边缘视角)时通常比正面视角更具反射性。StandardMaterial 和 PBRMaterial 都包含了菲涅尔效应。

在 StandardMaterial 上,您可以使用 FresnelParameters 对象明确控制漫反射、不透明度、反射和自发光组件的菲涅尔效应。

// Example: Add reflection Fresnel to a StandardMaterial
// 示例:为 StandardMaterial 添加反射菲涅尔效果
myStdMaterial.reflectionTexture = reflectionProbe.cubeTexture; // Needs a reflection source
// 需要一个反射源
myStdMaterial.reflectionFresnelParameters = new BABYLON.FresnelParameters();
myStdMaterial.reflectionFresnelParameters.bias = 0.1; // Controls falloff near center
// 控制中心附近的衰减
myStdMaterial.reflectionFresnelParameters.power = 2; // Controls sharpness of falloff
// 控制衰减的锐度
myStdMaterial.reflectionFresnelParameters.leftColor = BABYLON.Color3.White(); // Reflection color at grazing angle
// 掠射角时的反射颜色
myStdMaterial.reflectionFresnelParameters.rightColor = BABYLON.Color3.Black(); // Reflection color head-on
// 正面视角时的反射颜色

在 PBRMaterial 上,菲涅尔效应是基于物理原理自动计算的(使用折射率、金属度等因素)。除非为了非常特殊的效果,您通常不需要直接设置菲涅尔参数。

示例演示:标准材质与 PBR 材质对比

Section titled “示例演示:标准材质与 PBR 材质对比”

此示例演示并排显示两个球体。一个使用 StandardMaterial,另一个使用 PBRMetallicRoughnessMaterial。两者都试图看起来像红色塑料。请注意它们对光线和环境的反应有何不同。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>Babylon.js - Material Comparison</title>
<script src="https://cdn.babylonjs.com/babylon.js"></script>
<script src="https://cdn.babylonjs.com/loaders/babylonjs.loaders.min.js"></script> <!-- Needed for env texture -->
<!-- 环境纹理需要 -->
<style>
html, body { overflow: hidden; width: 100%; height: 100%; margin: 0; padding: 0; }
#renderCanvas { width: 100%; height: 100%; touch-action: none; }
</style>
</head>
<body>
<canvas id="renderCanvas"></canvas>
<script type="text/javascript">
const canvas = document.getElementById("renderCanvas");
const engine = new BABYLON.Engine(canvas, true);
const createScene = function () {
const scene = new BABYLON.Scene(engine);
// scene.clearColor = new BABYLON.Color4(0.2, 0.2, 0.25, 1.0);
// Environment Texture (Crucial for PBR)
// 环境纹理(对 PBR 至关重要)
try {
// Ensure 'textures/environment.env' exists
// 确保 'textures/environment.env' 存在
const envTexture = BABYLON.CubeTexture.CreateFromPrefilteredData("textures/environment.env", scene);
scene.environmentTexture = envTexture;
scene.createDefaultSkybox(envTexture, true, 1000, 0.3); // Add skybox using the env texture
// 使用环境纹理添加天空盒
} catch(err) {
console.error("Failed to load environment texture:", err);
// 加载环境纹理失败:
scene.clearColor = new BABYLON.Color4(0.2, 0.2, 0.25, 1.0);
// Add basic light as fallback if env texture fails
// 如果环境纹理加载失败,添加基础灯光作为备用
const light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0, 1, 0), scene);
light.intensity = 1.0;
}
const camera = new BABYLON.ArcRotateCamera("camera", -Math.PI / 2 * 1.2 , Math.PI / 2.5, 10, new BABYLON.Vector3(0, 1, 0), scene);
camera.attachControl(canvas, true);
camera.wheelPrecision = 100;
// Sphere 1: Standard Material (Red Plastic attempt)
// 球体 1:标准材质(尝试实现红色塑料)
const sphereStd = BABYLON.MeshBuilder.CreateSphere("sphereStd", { diameter: 2, segments: 32 }, scene);
sphereStd.position.x = -2;
sphereStd.position.y = 1;
const stdMat = new BABYLON.StandardMaterial("stdMat", scene);
stdMat.diffuseColor = new BABYLON.Color3(0.8, 0.1, 0.1); // Red
// 红色
stdMat.specularColor = new BABYLON.Color3(0.9, 0.9, 0.9); // Strong white highlights
// 强烈白色高光
stdMat.specularPower = 48; // Relatively sharp highlights for plastic
// 对于塑料来说相对锐利的高光
// Optional: Add subtle reflection from environment
// 可选:添加来自环境的微妙反射
// stdMat.reflectionTexture = scene.environmentTexture;
// stdMat.reflectionFresnelParameters = new BABYLON.FresnelParameters();
// stdMat.reflectionFresnelParameters.bias = 0.8; // Less reflection head-on
// 正面视角反射较少
sphereStd.material = stdMat;
// Sphere 2: PBR Material (Red Plastic attempt)
// 球体 2:PBR 材质(尝试实现红色塑料)
const spherePBR = BABYLON.MeshBuilder.CreateSphere("spherePBR", { diameter: 2, segments: 32 }, scene);
spherePBR.position.x = 2;
spherePBR.position.y = 1;
const pbrMat = new BABYLON.PBRMetallicRoughnessMaterial("pbrMat", scene);
pbrMat.baseColor = new BABYLON.Color3(0.8, 0.1, 0.1); // Red
// 红色
pbrMat.metallic = 0.1; // Low metallic for plastic
// 塑料的低金属度
pbrMat.roughness = 0.3; // Moderate roughness for plastic sheen
// 塑料光泽的中等粗糙度
// PBR uses scene.environmentTexture automatically for reflections
// PBR 会自动使用 scene.environmentTexture 进行反射
spherePBR.material = pbrMat;
return scene;
};
const scene = createScene();
engine.runRenderLoop(function () { scene.render(); });
window.addEventListener("resize", function () { engine.resize(); });
</script>
</body>
</html>

此示例演示在逼真的天空背景下(如果环境纹理加载成功)显示两个红色球体。左边的球体使用 StandardMaterial,右边的球体使用 PBRMaterial。观察 PBR 球体可能显示出更逼真的反射和高光,它们与天空盒环境自然地互动,而 StandardMaterial 球体的外观更多地取决于设置的特定 specularColor 和 specularPower 值。PBR 材质通常看起来更融入环境中。

为了使 PBR 材质和天空盒最佳工作,您需要一个预过滤的环境立方体贴图文件(例如 environment.env),位于 textures 文件夹中。您可以使用 Babylon.js Sandbox 或 Lys 等工具从 HDR 图像生成这些文件。