Skip to content

PointLight:点光源

点光源从一个点向所有方向发光。蜡烛、灯泡、篝火都是现实中的例子。与平行光不同,点光源有位置衰减范围

最小配置

rust
use bevy::prelude::*;

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_systems(Startup, setup)
        .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(Sphere::new(0.8).mesh().uv(32, 18))),
        MeshMaterial3d(materials.add(StandardMaterial {
            base_color: Color::srgb(0.9, 0.2, 0.2),
            metallic: 0.9,
            perceptual_roughness: 0.3,
            ..default()
        })),
        Transform::from_xyz(0.0, 0.8, 0.0),
    ));

    // 点光源:挂在球体正上方,加一盏小灯球做视觉提示
    commands.spawn((
        PointLight {
            intensity: 50_000.0,  // 流明
            range: 6.0,
            radius: 0.1,
            contact_shadows_enabled: true,
            ..default()
        },
        Transform::from_xyz(0.0, 3.0, 0.0),
        children![(
            Mesh3d(meshes.add(Sphere::new(0.08).mesh().uv(8, 8))),
            MeshMaterial3d(materials.add(StandardMaterial {
                base_color: Color::srgb(10.0, 10.0, 10.0),
                emissive: LinearRgba::new(5.0, 5.0, 5.0, 0.0),
                ..default()
            })),
        )],
    ));

    // 相机
    commands.spawn((
        Camera3d::default(),
        Transform::from_xyz(4.0, 2.5, 5.0).looking_at(Vec3::new(0.0, 0.8, 0.0), Vec3::Y),
    ));
}

Listing 22-2:点光源——强度、范围与衰减半径

四个关键参数

参数含义默认值影响
intensity光通量,流明(lm)相当于大型影院灯决定了亮度峰值
range光照最远距离(米)20.0超出此范围完全无光
radius光源半径(米)0.0影响高光大小和软阴影半影
contact_shadows_enabled是否投阴影false启用后性能开销显著

intensity 的建议取值为 light_consts::lumens 模块中的参考值:

流明对应实物
LUMEN_FAMILY_ROOM50客厅灯
LUMEN_OFFICE320—500办公室照明
VERY_LARGE_CINEMA_LIGHT100,000大型影院灯

范围与衰减

range 不是硬截止——Bevy 在 range 内使用物理正确的平方反比衰减,超出后完全截断。因此 range 应与 intensity 配合调整:高强度配大范围,避免截断处出现视觉硬边。

小灯球技巧

在点光源实体下加一个子实体做发光球体,是一种常见的视觉提示手法。子实体用 emissive(自发光)材质表现灯体自身发光:

rust
children![(
    Mesh3d(meshes.add(Sphere::new(0.08).mesh().uv(8, 8))),
    MeshMaterial3d(materials.add(StandardMaterial {
        base_color: Color::srgb(10.0, 10.0, 10.0),
        emissive: LinearRgba::new(5.0, 5.0, 5.0, 0.0),
        ..default()
    })),
)]