BabylonJS - 材质
Babylon.js - 材质
Section titled “Babylon.js - 材质”材质(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;标准材质纹理
Section titled “标准材质纹理”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 纹理
Section titled “PBR 纹理”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 图像生成这些文件。