Babylon.js 光照系统 #
光照概述 #
光照是 3D 场景中最重要的元素之一,它决定了场景的视觉效果和氛围。Babylon.js 提供了多种光源类型,可以模拟真实世界的各种光照效果。
text
┌─────────────────────────────────────────────────────────────┐
│ Babylon.js 光源类型 │
├─────────────────────────────────────────────────────────────┤
│ │
│ HemisphericLight ─── 半球光(环境光) │
│ - 模拟天空散射光 │
│ - 无方向性,均匀照亮场景 │
│ │
│ DirectionalLight ─── 方向光(太阳光) │
│ - 平行光线,模拟太阳光 │
│ - 适合户外场景 │
│ │
│ PointLight ──────── 点光源 │
│ - 从一点向四周发散 │
│ - 模拟灯泡、火焰等 │
│ │
│ SpotLight ───────── 聚光灯 │
│ - 锥形光束 │
│ - 模拟手电筒、舞台灯光 │
│ │
└─────────────────────────────────────────────────────────────┘
HemisphericLight 半球光 #
半球光模拟天空散射光,是最简单的环境光源。
基本创建 #
javascript
const light = new BABYLON.HemisphericLight(
'hemiLight',
new BABYLON.Vector3(0, 1, 0), // 方向(指向天空)
scene
);
光照属性 #
javascript
// 光照强度
light.intensity = 0.7;
// 光照颜色
light.diffuse = new BABYLON.Color3(1, 1, 1); // 主光源颜色
light.groundColor = new BABYLON.Color3(0.4, 0.4, 0.4); // 地面反射颜色
light.specular = new BABYLON.Color3(1, 1, 1); // 高光颜色
方向影响 #
text
┌─────────────────────────────────────────────────────────────┐
│ 半球光方向影响 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ↑ 方向向量 │
│ │ │
│ ┌─────────┼─────────┐ │
│ │ 天空颜色 │ │
│ │ (diffuse) │ │
│ │ │ │ │
│ ├─────────●─────────┤ ← 物体表面 │
│ │ │ │ │
│ │ 地面颜色 │ │
│ │ (groundColor) │ │
│ └───────────────────┘ │
│ │
│ 向上的面:使用天空颜色 │
│ 向下的面:使用地面颜色 │
│ 侧面:混合两种颜色 │
│ │
└─────────────────────────────────────────────────────────────┘
使用场景 #
javascript
// 室外场景 - 蓝天
const skyLight = new BABYLON.HemisphericLight('sky', new BABYLON.Vector3(0, 1, 0), scene);
skyLight.diffuse = new BABYLON.Color3(0.6, 0.7, 0.9);
skyLight.groundColor = new BABYLON.Color3(0.4, 0.3, 0.2);
skyLight.intensity = 0.8;
// 室内场景 - 柔和光线
const indoorLight = new BABYLON.HemisphericLight('indoor', new BABYLON.Vector3(0, 1, 0), scene);
indoorLight.diffuse = new BABYLON.Color3(1, 0.95, 0.9);
indoorLight.groundColor = new BABYLON.Color3(0.3, 0.3, 0.3);
indoorLight.intensity = 0.5;
DirectionalLight 方向光 #
方向光产生平行光线,模拟太阳光。
基本创建 #
javascript
const light = new BABYLON.DirectionalLight(
'dirLight',
new BABYLON.Vector3(-1, -2, -1), // 光线方向
scene
);
光照属性 #
javascript
// 光照强度
light.intensity = 1.0;
// 光照颜色
light.diffuse = new BABYLON.Color3(1, 1, 0.9); // 暖色调阳光
light.specular = new BABYLON.Color3(1, 1, 1);
// 光源位置(用于阴影计算)
light.position = new BABYLON.Vector3(50, 100, 50);
// 光照范围
light.range = 200;
方向设置 #
javascript
// 从右上方向左下方照射
light.direction = new BABYLON.Vector3(-1, -2, -1);
// 从正上方照射
light.direction = new BABYLON.Vector3(0, -1, 0);
// 模拟日落
light.direction = new BABYLON.Vector3(-1, -0.3, 0);
light.diffuse = new BABYLON.Color3(1, 0.6, 0.3);
PointLight 点光源 #
点光源从一点向四周发散光线。
基本创建 #
javascript
const light = new BABYLON.PointLight(
'pointLight',
new BABYLON.Vector3(0, 5, 0), // 光源位置
scene
);
光照属性 #
javascript
// 光照强度
light.intensity = 1.0;
// 光照颜色
light.diffuse = new BABYLON.Color3(1, 0.9, 0.8);
light.specular = new BABYLON.Color3(1, 1, 1);
// 光照范围
light.range = 20;
// 衰减
light.attenuationStartDistance = 5;
light.attenuationEndDistance = 20;
衰减模式 #
text
┌─────────────────────────────────────────────────────────────┐
│ 点光源衰减 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ● 光源位置 │
│ │ │
│ ┌────────┼────────┐ │
│ │ 衰减开始距离 │ │
│ │ attenuationStart │ │
│ └────────┼────────┘ │
│ │ │
│ ┌────────┼────────┐ │
│ │ 衰减结束距离 │ │
│ │ attenuationEnd │ │
│ └────────┼────────┘ │
│ │ │
│ 光照强度 = 0 │
│ │
│ 内圈:光照强度 = intensity │
│ 中间:逐渐衰减 │
│ 外圈:光照强度 = 0 │
│ │
└─────────────────────────────────────────────────────────────┘
动态点光源 #
javascript
// 火焰效果
const fireLight = new BABYLON.PointLight('fire', new BABYLON.Vector3(0, 1, 0), scene);
fireLight.diffuse = new BABYLON.Color3(1, 0.5, 0.1);
fireLight.range = 10;
scene.onBeforeRenderObservable.add(() => {
// 随机闪烁
fireLight.intensity = 0.8 + Math.random() * 0.4;
fireLight.position.x = Math.sin(Date.now() * 0.01) * 0.1;
});
SpotLight 聚光灯 #
聚光灯产生锥形光束,适合手电筒、舞台灯光效果。
基本创建 #
javascript
const light = new BABYLON.SpotLight(
'spotLight',
new BABYLON.Vector3(0, 10, 0), // 位置
new BABYLON.Vector3(0, -1, 0), // 方向
Math.PI / 4, // 光锥角度
2, // 光锥衰减指数
scene
);
光照属性 #
javascript
// 光照强度
light.intensity = 1.0;
// 光照颜色
light.diffuse = new BABYLON.Color3(1, 1, 1);
light.specular = new BABYLON.Color3(1, 1, 1);
// 光照范围
light.range = 30;
// 光锥角度(弧度)
light.angle = Math.PI / 4;
// 光锥边缘衰减
light.innerAngle = Math.PI / 6;
light.penumbra = 0.5;
聚光灯参数 #
text
┌─────────────────────────────────────────────────────────────┐
│ 聚光灯参数示意 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ● 光源位置 │
│ │ │
│ │ direction │
│ ▼ │
│ ┌───┴───┐ │
│ ╱ │ ╲ angle (外锥角) │
│ ╱ │ ╲ │
│ ╱ ┌────┼────┐ ╲ │
│ ╱ │ 内锥角 │ ╲ │
│ ╱ │(inner)│ ╲ │
│ ●────────┴───────┴────────● │
│ range │
│ │
│ angle: 光锥总角度 │
│ innerAngle: 内锥角度(完全照亮区域) │
│ penumbra: 边缘柔和度(0-1) │
│ range: 光照范围 │
│ │
└─────────────────────────────────────────────────────────────┘
手电筒效果 #
javascript
const flashlight = new BABYLON.SpotLight(
'flashlight',
camera.position.clone(),
camera.getForwardRay().direction,
Math.PI / 8,
2,
scene
);
flashlight.intensity = 2;
flashlight.range = 50;
// 跟随相机
scene.onBeforeRenderObservable.add(() => {
flashlight.position = camera.position.clone();
flashlight.direction = camera.getForwardRay().direction;
});
阴影系统 #
基本阴影 #
javascript
// 创建方向光
const light = new BABYLON.DirectionalLight(
'dirLight',
new BABYLON.Vector3(-1, -2, -1),
scene
);
light.position = new BABYLON.Vector3(20, 40, 20);
// 创建阴影生成器
const shadowGenerator = new BABYLON.ShadowGenerator(1024, light);
// 添加投射阴影的物体
shadowGenerator.addShadowCaster(mesh);
// 设置接收阴影的地面
ground.receiveShadows = true;
阴影类型 #
text
┌─────────────────────────────────────────────────────────────┐
│ 阴影贴图类型 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1. Basic Shadow Map │
│ - 最基础的阴影 │
│ - 性能最好,质量一般 │
│ │
│ 2. PCF (Percentage Closer Filtering) │
│ - 边缘柔和的阴影 │
│ - 性能和质量平衡 │
│ │
│ 3. PCSS (Percentage Closer Soft Shadows) │
│ - 软阴影效果 │
│ - 根据距离变化软硬 │
│ │
│ 4. ESM (Exponential Shadow Map) │
│ - 指数阴影贴图 │
│ - 适合大面积场景 │
│ │
│ 5. CSM (Cascaded Shadow Maps) │
│ - 级联阴影贴图 │
│ - 大场景高质量阴影 │
│ │
└─────────────────────────────────────────────────────────────┘
PCF 柔和阴影 #
javascript
const shadowGenerator = new BABYLON.ShadowGenerator(2048, light);
// 使用 PCF
shadowGenerator.usePercentageCloserFiltering = true;
shadowGenerator.filteringQuality = BABYLON.ShadowGenerator.QUALITY_HIGH;
// 添加阴影投射者
shadowGenerator.addShadowCaster(box);
shadowGenerator.addShadowCaster(sphere);
// 接收阴影
ground.receiveShadows = true;
PCSS 软阴影 #
javascript
const shadowGenerator = new BABYLON.ShadowGenerator(2048, light);
// 使用 PCSS
shadowGenerator.usePercentageCloserSoftShadows = true;
shadowGenerator.useContactHardeningShadow = true;
// 设置阴影参数
shadowGenerator.contactHardeningLightSizeUVRatio = 0.2;
阴影属性设置 #
javascript
// 阴影贴图尺寸
const shadowGenerator = new BABYLON.ShadowGenerator(2048, light);
// 阴影偏移(防止阴影痤疮)
shadowGenerator.bias = 0.0001;
shadowGenerator.normalBias = 0.02;
// 阴影范围
shadowGenerator.minZ = 0;
shadowGenerator.maxZ = 100;
// 阴影颜色
shadowGenerator.setDarkness(0.5); // 0-1,越小越暗
// 阴影透明度
shadowGenerator.useBlurExponentialShadowMap = true;
shadowGenerator.blurKernel = 32;
点光源阴影 #
javascript
const pointLight = new BABYLON.PointLight(
'pointLight',
new BABYLON.Vector3(0, 5, 0),
scene
);
// 创建阴影生成器
const shadowGenerator = new BABYLON.ShadowGenerator(1024, pointLight);
// 对于点光源,需要使用立方体阴影贴图
shadowGenerator.useCubeShadowMap = true;
shadowGenerator.addShadowCaster(mesh);
ground.receiveShadows = true;
光照高级特性 #
光照排除 #
javascript
// 排除特定网格
light.excludedMeshes.push(mesh1, mesh2);
// 只照亮特定网格
light.includedOnlyMeshes.push(mesh1, mesh2);
// 阴影排除
shadowGenerator.excludedMeshes.push(mesh);
光照图层 #
javascript
// 创建图层
const layer1 = new BABYLON.Layer('layer1');
// 设置光照影响图层
light.includeOnlyWithLayerMask = layer1.layerMask;
// 设置网格图层
mesh.layerMask = layer1.layerMask;
光照动画 #
javascript
// 光照强度动画
const lightAnimation = new BABYLON.Animation(
'lightIntensity',
'intensity',
30,
BABYLON.Animation.ANIMATIONTYPE_FLOAT,
BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE
);
lightAnimation.setKeys([
{ frame: 0, value: 0 },
{ frame: 30, value: 1 },
{ frame: 60, value: 0 }
]);
light.animations.push(lightAnimation);
scene.beginAnimation(light, 0, 60, true);
// 光源位置动画
const positionAnimation = new BABYLON.Animation(
'lightPosition',
'position',
30,
BABYLON.Animation.ANIMATIONTYPE_VECTOR3,
BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE
);
positionAnimation.setKeys([
{ frame: 0, value: new BABYLON.Vector3(-10, 5, 0) },
{ frame: 60, value: new BABYLON.Vector3(10, 5, 0) }
]);
light.animations.push(positionAnimation);
scene.beginAnimation(light, 0, 60, true);
全局光照 #
环境贴图 #
javascript
// 加载 HDR 环境贴图
const hdrTexture = new BABYLON.CubeTexture.CreateFromPrefilteredData(
'/textures/environment.env',
scene
);
// 设置环境贴图
scene.environmentTexture = hdrTexture;
// 环境贴图强度
scene.environmentIntensity = 0.5;
辐照度 #
javascript
// 创建辐照度探针
const irradianceProbe = new BABYLON.IrradianceVolume(scene);
// 设置辐照度
irradianceProbe.diffuse = new BABYLON.SolidParticleSystem('diffuse', scene);
光照性能优化 #
光照剔除 #
javascript
// 启用光照剔除
light.range = 20;
// 只照亮范围内的物体
light.includeOnlyMeshes(scene.meshes.filter(m => {
return BABYLON.Vector3.Distance(m.position, light.position) < light.range;
}));
光照 LOD #
javascript
// 根据距离调整光照强度
scene.onBeforeRenderObservable.add(() => {
const distance = BABYLON.Vector3.Distance(camera.position, light.position);
light.intensity = Math.max(0, 1 - distance / 50);
});
阴影优化 #
javascript
// 降低阴影贴图分辨率
const shadowGenerator = new BABYLON.ShadowGenerator(512, light);
// 使用简单阴影
shadowGenerator.usePoissonSampling = false;
shadowGenerator.useBlurExponentialShadowMap = false;
// 限制阴影范围
shadowGenerator.minZ = 5;
shadowGenerator.maxZ = 50;
实战:场景光照设计 #
javascript
function setupLighting(scene) {
// 1. 环境光 - 基础照明
const hemiLight = new BABYLON.HemisphericLight(
'hemi',
new BABYLON.Vector3(0, 1, 0),
scene
);
hemiLight.intensity = 0.3;
hemiLight.diffuse = new BABYLON.Color3(0.8, 0.85, 1);
hemiLight.groundColor = new BABYLON.Color3(0.2, 0.2, 0.25);
// 2. 主光源 - 太阳光
const sunLight = new BABYLON.DirectionalLight(
'sun',
new BABYLON.Vector3(-1, -2, -1),
scene
);
sunLight.position = new BABYLON.Vector3(50, 100, 50);
sunLight.intensity = 0.8;
sunLight.diffuse = new BABYLON.Color3(1, 0.95, 0.9);
// 3. 阴影
const shadowGenerator = new BABYLON.ShadowGenerator(2048, sunLight);
shadowGenerator.usePercentageCloserFiltering = true;
shadowGenerator.filteringQuality = BABYLON.ShadowGenerator.QUALITY_HIGH;
shadowGenerator.bias = 0.0001;
// 4. 补光
const fillLight = new BABYLON.DirectionalLight(
'fill',
new BABYLON.Vector3(1, -0.5, 1),
scene
);
fillLight.intensity = 0.3;
fillLight.diffuse = new BABYLON.Color3(0.7, 0.75, 0.8);
// 5. 点光源 - 室内灯光
const pointLight = new BABYLON.PointLight(
'lamp',
new BABYLON.Vector3(0, 3, 0),
scene
);
pointLight.intensity = 0.5;
pointLight.diffuse = new BABYLON.Color3(1, 0.9, 0.7);
pointLight.range = 15;
return {
hemiLight,
sunLight,
fillLight,
pointLight,
shadowGenerator
};
}
// 使用
const lights = setupLighting(scene);
// 添加阴影投射者
scene.meshes.forEach(mesh => {
if (mesh.name !== 'ground') {
lights.shadowGenerator.addShadowCaster(mesh);
}
});
// 地面接收阴影
ground.receiveShadows = true;
下一步 #
现在你已经掌握了光照系统,接下来学习 材质系统,了解如何为物体添加材质和纹理!
最后更新:2026-03-29