Skip to content

DirectionalLight:平行光

平行光模拟距离极远的光源。太阳是典型的例子——从场景中看,所有光线近似平行,照射方向一致。

最小配置

DirectionalLight 是一个组件,挂在实体上。光照方向由实体的 Transform 的 forward(-Z)方向决定:

rust
use std::f32::consts::PI;

use bevy::prelude::*;

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_systems(Startup, setup)
        .add_systems(Update, rotate_sun)
        .run();
}

fn setup(
    mut commands: Commands,
    mut meshes: ResMut<Assets<Mesh>>,
    mut materials: ResMut<Assets<StandardMaterial>>,
) {
    // 地面
    commands.spawn((
        Mesh3d(meshes.add(Plane3d::default().mesh().size(8.0, 8.0))),
        MeshMaterial3d(materials.add(StandardMaterial {
            base_color: Color::srgb(0.3, 0.3, 0.3),
            perceptual_roughness: 1.0,
            ..default()
        })),
    ));

    // 展示物体——立方体、球体、圆环
    commands.spawn((
        Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0))),
        MeshMaterial3d(materials.add(StandardMaterial {
            base_color: Color::srgb(0.8, 0.2, 0.2),
            metallic: 0.5,
            perceptual_roughness: 0.3,
            ..default()
        })),
        Transform::from_xyz(-1.5, 0.5, 0.0),
    ));

    commands.spawn((
        Mesh3d(meshes.add(Sphere::new(0.6).mesh().uv(32, 18))),
        MeshMaterial3d(materials.add(StandardMaterial {
            base_color: Color::srgb(0.2, 0.6, 0.8),
            metallic: 0.9,
            perceptual_roughness: 0.2,
            ..default()
        })),
        Transform::from_xyz(0.0, 0.6, 0.0),
    ));

    commands.spawn((
        Mesh3d(meshes.add(Torus::default())),
        MeshMaterial3d(materials.add(StandardMaterial {
            base_color: Color::srgb(0.9, 0.7, 0.1),
            metallic: 0.8,
            perceptual_roughness: 0.4,
            ..default()
        })),
        Transform::from_xyz(1.5, 0.5, 0.0),
    ));

    // DirectionalLight:太阳
    // 光照方向沿 Transform 的 forward(-Z),此处让光从斜上方照下
    commands.spawn((
        DirectionalLight {
            illuminance: light_consts::lux::FULL_DAYLIGHT,
            contact_shadows_enabled: true,
            ..default()
        },
        Transform::from_xyz(0.0, 5.0, 0.0)
            .looking_at(Vec3::new(0.0, 0.0, -1.0), Vec3::Y),
    ));

    // 相机
    commands.spawn((
        Camera3d::default(),
        Transform::from_xyz(4.0, 3.0, 5.0).looking_at(Vec3::ZERO, Vec3::Y),
    ));
}

fn rotate_sun(time: Res<Time>, mut query: Query<&mut Transform, With<DirectionalLight>>) {
    for mut transform in &mut query {
        transform.rotate_y(time.delta_secs() * 0.2);
    }
}

Listing 22-1:DirectionalLight 最小配置——太阳绕 Y 轴旋转

illuminance 字段的单位是勒克斯(lux),表示单位面积上接收的光通量。light_consts::lux 模块提供了一组参考值:

对应场景
FULL_DAYLIGHT (10,000)晴天的直射阳光
OVERCAST_DAY (1,000)阴天
AMBIENT_DAYLIGHT (100)白天的环境光

contact_shadows_enabled: true 启用阴影投射。平行光的阴影实现基于级联阴影映射(CSM),由 CascadeShadowConfig 组件控制(见 22.5 节)。

方向由旋转决定

DirectionalLight 的位置字段不影响光照——平行光没有位置概念。只有旋转决定光线方向。代码中的 transform.looking_at(target, up) 是一种方便的朝向设定方式。

颜色与强度

color 字段设置光色,illuminance 决定强度:

rust
DirectionalLight {
    color: Color::srgb(1.0, 0.95, 0.8),  // 暖色日光
    illuminance: light_consts::lux::FULL_DAYLIGHT,
    ..default()
}

冷色光(偏蓝)模拟月光,暖色光(偏黄)模拟日出/日落。