环境光与反射环境贴图
场景中除了直接光源,还需要对暗部的照明进行兜底。Bevy 提供两层兜底机制:GlobalAmbientLight 提供廉价的无方向填充光;EnvironmentMapLight 提供基于 HDRI 贴图的反射与漫反射照明。
GlobalAmbientLight
GlobalAmbientLight 是一个 Resource,作用于整个场景。它的光照无方向、无阴影、不计衰减——纯粹给背光面一个"看得见"的亮度:
rust
use bevy::prelude::*;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
// 默认 GlobalAmbientLight 亮度 80,此处调暗以凸显环境光的效果
.insert_resource(GlobalAmbientLight {
color: Color::srgb(0.2, 0.2, 0.5),
brightness: 60.0,
..default()
})
.add_systems(Startup, setup)
.add_systems(Update, (toggle_ambient, adjust_brightness))
.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.4, 0.4, 0.4),
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.2, 0.6, 0.8),
..default()
})),
Transform::from_xyz(-1.2, 0.5, 0.0),
));
commands.spawn((
Mesh3d(meshes.add(Sphere::new(0.5).mesh().uv(32, 18))),
MeshMaterial3d(materials.add(StandardMaterial {
base_color: Color::srgb(0.9, 0.1, 0.1),
..default()
})),
Transform::from_xyz(1.2, 0.5, 0.0),
));
// 本场景没有 DirectionalLight、PointLight、SpotLight
// 只有 GlobalAmbientLight 提供全场景的兜底照明
// 相机
commands.spawn((
Camera3d::default(),
Transform::from_xyz(4.0, 3.0, 5.0).looking_at(Vec3::ZERO, Vec3::Y),
));
}
fn toggle_ambient(key_input: Res<ButtonInput<KeyCode>>, mut ambient: ResMut<GlobalAmbientLight>) {
if key_input.just_pressed(KeyCode::Space) {
ambient.brightness = if ambient.brightness > 1.0 { 0.0 } else { 60.0 };
}
}
fn adjust_brightness(
key_input: Res<ButtonInput<KeyCode>>,
time: Res<Time>,
mut ambient: ResMut<GlobalAmbientLight>,
) {
if key_input.pressed(KeyCode::ArrowUp) {
ambient.brightness += time.delta_secs() * 60.0;
}
if key_input.pressed(KeyCode::ArrowDown) {
ambient.brightness = (ambient.brightness - time.delta_secs() * 60.0).max(0.0);
}
}Listing 22-4:GlobalAmbientLight 的设置与运行时调节
| 字段 | 含义 |
|---|---|
color | 环境光颜色 |
brightness | 亮度乘数,单位 cd/m² |
affects_lightmapped_meshes | 是否影响已烘焙光照贴图的网格 |
默认值 color: WHITE、brightness: 80.0。Listing 22-4 将其调低并设成蓝紫色以凸显效果。
运行时通过 Space 键开关、上下键调节亮度,可以直观对比环境光有无的差别。
各光源的环境光策略
- 有 DirectionalLight/PointLight/SpotLight 的场景:
brightness设为 20—80 即可,避免盖过直接光的方向感 - 只有 AmbientLight 的场景:展示物体在没有直接光时的形态,适合用作调试或风格化渲染
brightness: 0.0:无环境光,背光面完全纯黑。需要与直接光配合使用
EnvironmentMapLight
EnvironmentMapLight 提供基于图像的照明(IBL)。它用一对立方体贴图(diffuse + specular)来模拟环境反射:
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>>,
asset_server: Res<AssetServer>,
) {
// 地面
commands.spawn((
Mesh3d(meshes.add(Plane3d::default().mesh().size(6.0, 6.0))),
MeshMaterial3d(materials.add(StandardMaterial {
base_color: Color::srgb(0.3, 0.3, 0.3),
perceptual_roughness: 0.8,
..default()
})),
));
// 高反射金属球——环境贴图在它身上最明显
commands.spawn((
Mesh3d(meshes.add(Sphere::new(0.8).mesh().uv(64, 36))),
MeshMaterial3d(materials.add(StandardMaterial {
base_color: Color::srgb(0.8, 0.8, 0.8),
metallic: 1.0,
perceptual_roughness: 0.05,
..default()
})),
Transform::from_xyz(0.0, 0.8, 0.0),
));
// EnvironmentMapLight:用 .hdr 等距柱面图生成环境贴图。
// 把 EnvironmentMapLight 挂在相机上,作用于整个画面。
// 需要的 .hdr 文件可用工具(如 Blender、HDRI Haven)生成或下载。
commands.spawn((
Camera3d::default(),
Transform::from_xyz(3.5, 2.5, 5.0).looking_at(Vec3::ZERO, Vec3::Y),
EnvironmentMapLight {
diffuse_map: asset_server.load("environment_maps/pisa_diffuse_8k.jpg"),
specular_map: asset_server.load("environment_maps/pisa_specular_8k.jpg"),
intensity: 500.0,
..default()
},
));
}Listing 22-6:EnvironmentMapLight——需要 .hdr 贴图文件
EnvironmentMapLight 作为组件挂在相机实体上,为整个画面提供环境反射信息。标 intensity 控制反射强度。
前置条件:需要准备一张 .hdr 格式的等距柱面投影环境贴图。工具链包括 Blender(导出 HDR)、HDRI Haven(下载)、或 Bevy 官方示例仓库中的测试贴图。
EnvironmentMapLight 对高反射材质的效果最为明显——金属球上清晰倒映出周围环境。光探针(LightProbe) 是其进阶用法,能将环境照明限定在场景的特定空间区域,在第 24 章结合 PBR 材质深入讨论。