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