Skip to content

BabylonJS - 光源

光源对于照亮你的 3D 场景并使你的网格可见至关重要。没有光源,大多数物体会显得漆黑一片。Babylon.js 提供了几种不同类型的光源,每种都模拟了现实世界中不同的照明场景,并提供了不同级别的控制和性能特性。

光源与材质相互作用,决定了网格上每个像素的最终颜色。受光源影响的关键属性包括 diffuse 颜色(直射光下的基础颜色)和 specular 颜色(闪亮表面上的高光颜色)。PBR 材质以更符合物理规律的方式与光源相互作用,考虑了粗糙度和金属度等因素。

Babylon.js 提供四种主要类型的光源:

这种光源模拟环境室外光照,就像天空一样。它不来自特定的点,而是根据方向(通常指向正上方)照亮整个场景。它有三个颜色属性:

  • diffuse: 来自指定方向的光颜色(如天空)。
  • specular: 镜面高光的颜色(对于半球光通常不太相关)。
  • groundColor: 从下方反射的光颜色(与主要方向相反,如地面反弹的光)。

它非常适合提供基本的、开销小的环境照明,以防止出现完全黑暗的阴影区域。

const light = new BABYLON.HemisphericLight(
"hemiLight",
new BABYLON.Vector3(0, 1, 0), // 方向 (0,1,0 表示光源来自上方)
scene
);
light.intensity = 0.7; // 整体亮度
light.diffuse = new BABYLON.Color3(0.8, 0.85, 1.0); // 天空颜色 (浅蓝色)
light.groundColor = new BABYLON.Color3(0.4, 0.35, 0.3); // 地面反弹光颜色 (棕色)
light.specular = new BABYLON.Color3(0.5, 0.5, 0.5); // 微妙的镜面反射

点光源从空间中的一个点向所有方向均匀发光,就像一个裸露的灯泡。其强度随距离衰减(衰减)。

const light = new BABYLON.PointLight(
"pointLight",
new BABYLON.Vector3(5, 3, -2), // 光源位置
scene
);
light.intensity = 0.8;
light.diffuse = new BABYLON.Color3(1, 0.8, 0.5); // 暖色光颜色
light.specular = new BABYLON.Color3(1, 1, 1); // 白色高光
// 可选:控制光强随距离衰减
// light.range = 20; // 光照影响的最大距离

模拟遥远的光源,如太阳,其光线实际上是平行的。它由方向而不是位置定义。所有物体无论距离“光源”多远都受到同等照明。平行光非常适合投射阴影。

const light = new BABYLON.DirectionalLight(
"dirLight",
new BABYLON.Vector3(-0.5, -1, 0.3), // 光源照射方向
scene
);
light.intensity = 1.0;
light.diffuse = new BABYLON.Color3(1, 1, 0.9); // 太阳光颜色
light.specular = new BABYLON.Color3(0.2, 0.2, 0.1);
// 要启用阴影,你需要一个 ShadowGenerator
const shadowGenerator = new BABYLON.ShadowGenerator(1024, light); // 贴图尺寸,光源
// 添加需要投射阴影的网格
// shadowGenerator.addShadowCaster(meshThatCastsShadow);
// 确保接收阴影的网格设置 receiveShadows = true
// groundMesh.receiveShadows = true;

聚光灯从一个点发出定向的光,光线限制在一个圆锥形内,就像手电筒或舞台射灯。它由位置、方向、角度(光锥宽度)和指数(光的集中程度)定义。

const light = new BABYLON.SpotLight(
"spotLight",
new BABYLON.Vector3(2, 5, -3), // 聚光灯位置
new BABYLON.Vector3(-0.2, -1, 0.3), // 聚光灯照射方向
Math.PI / 3, // 光锥角度 (弧度制)
2, // 指数 (聚光程度)
scene
);
light.intensity = 1.2;
light.diffuse = new BABYLON.Color3(0.5, 1, 0.5); // 绿色光
light.specular = new BABYLON.Color3(1, 1, 1);
  • intensity: 整体亮度乘数 (默认值 1.0)。
  • diffuse: 影响漫反射的主光源颜色 (Vector3)。
  • specular: 影响镜面反射高光的光源颜色 (Vector3)。
  • setEnabled(boolean): 打开或关闭光源。
  • range (PointLight, SpotLight): 光照影响的最大距离。
  • shadowEnabled (Directional, Spot, Point): 标志,指示光源是否能投射阴影 (需要 ShadowGenerator)。

这个演示展示了一个包含地面和球体的场景,场景由半球光提供环境补充光,点光源提供局部的暖色光,以及一个可能投射阴影的平行光(阴影在此基础示例中未完全实现)照亮。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>Babylon.js - Light Types Demo</title>
<script src="https://cdn.babylonjs.com/babylon.js"></script>
<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, 0, 0, 1.0); // 黑色背景
const camera = new BABYLON.ArcRotateCamera("camera", -Math.PI / 2 * 1.5, Math.PI / 2.2, 25, new BABYLON.Vector3(0, 2, 0), scene);
camera.attachControl(canvas, true);
// --- 光源 ---
// 1. 环境补充光
const hemiLight = new BABYLON.HemisphericLight("hemiLight", new BABYLON.Vector3(0, 1, 0), scene);
hemiLight.intensity = 0.3;
hemiLight.groundColor = new BABYLON.Color3(0.1, 0.1, 0.1);
hemiLight.diffuse = new BABYLON.Color3(0.3, 0.3, 0.4);
// 2. 点光源 (暖色)
const pointLight = new BABYLON.PointLight("pointLight", new BABYLON.Vector3(5, 5, -5), scene);
pointLight.intensity = 0.8;
pointLight.diffuse = new BABYLON.Color3(1, 0.7, 0.3);
// 可视化点光源
const pointLightSphere = BABYLON.MeshBuilder.CreateSphere("plSphere", {diameter: 0.5}, scene);
pointLightSphere.position = pointLight.position;
const plMat = new BABYLON.StandardMaterial("plMat", scene);
plMat.emissiveColor = pointLight.diffuse; // 使球体发出光源颜色的光
pointLightSphere.material = plMat;
// 3. 平行光 (冷色调,潜在的阴影投射源)
const dirLight = new BABYLON.DirectionalLight("dirLight", new BABYLON.Vector3(-0.5, -0.8, 0.3), scene);
dirLight.intensity = 0.6;
dirLight.diffuse = new BABYLON.Color3(0.8, 0.9, 1.0);
// 如果需要阴影设置,会放在这里
// ----------------
// --- 网格 ---
const sphere = BABYLON.MeshBuilder.CreateSphere("sphere", { diameter: 4, segments: 32 }, scene);
sphere.position.y = 2;
const sphereMat = new BABYLON.StandardMaterial("sphereMat", scene);
sphereMat.diffuseColor = new BABYLON.Color3(0.8, 0.8, 0.8);
sphereMat.specularColor = new BABYLON.Color3(0.5, 0.5, 0.5);
sphereMat.specularPower = 32;
sphere.material = sphereMat;
const ground = BABYLON.MeshBuilder.CreateGround("ground", { width: 20, height: 20 }, scene);
const groundMat = new BABYLON.StandardMaterial("groundMat", scene);
groundMat.diffuseColor = new BABYLON.Color3(0.4, 0.5, 0.4); // 偏绿的地面
groundMat.specularColor = new BABYLON.Color3(0.1, 0.1, 0.1);
ground.material = groundMat;
// ground.receiveShadows = true; // 如果启用了阴影,需要此设置
// ----------------
return scene;
};
const scene = createScene();
engine.runRenderLoop(function () { scene.render(); });
window.addEventListener("resize", function () { engine.resize(); });
</script>
</body>
</html>

此演示显示一个灰色球体放置在偏绿的地面上,背景为黑色。场景由多种光源照亮:一个暗淡、偏冷的环境光(半球光)、一个从可见的发光球体(点光源)发出的较亮的暖色光,以及一个从某个角度射入的略带冷色的平行光。当你旋转相机时,这些光源的相互作用会在球体和地面上产生不同的颜色和高光效果。

基于物理的渲染(PBR)材质(如 PBRMaterial、PBRMetallicRoughnessMaterial 等)与光源的交互更为真实。除了用于直射光和阴影的标准光源外,它们通常高度依赖于 scene.environmentTexture(基于图像的光照)来提供环境光和反射。使用 PBR 时,HemisphericLight 的效果可能不如其在 StandardMaterial 上的效果明显,或者需要进行不同的调整。