材质球画廊
前面六节拆开了 StandardMaterial 的各个参数组。本节把它们合在一起:十二颗球、十二种现实材质,排成画廊。
rust
use bevy::prelude::*;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Startup, setup)
.add_systems(Update, rotate_camera)
.run();
}
fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
let sphere = meshes.add(Sphere::new(0.5).mesh().uv(64, 36));
let gallery: [(Color, f32, f32, &str); 12] = [
(Color::srgb(0.9, 0.1, 0.1), 0.0, 0.3, "红漆"),
(Color::srgb(0.1, 0.1, 0.9), 0.0, 0.1, "蓝瓷"),
(Color::srgb(1.0, 0.85, 0.0), 1.0, 0.2, "黄金"),
(Color::srgb(0.7, 0.7, 0.7), 1.0, 0.05, "铬镜"),
(Color::srgb(0.4, 0.25, 0.1), 0.0, 0.9, "旧木"),
(Color::srgb(0.15, 0.15, 0.15), 0.0, 0.7, "沥青"),
(Color::srgb(0.95, 0.95, 0.95), 0.0, 0.5, "白纸"),
(Color::srgb(0.6, 0.3, 0.1), 1.0, 0.6, "铜锈"),
(Color::srgb(0.2, 0.6, 0.3), 0.0, 0.4, "绿漆"),
(Color::srgb(0.8, 0.8, 0.85), 1.0, 0.15, "不锈钢"),
(Color::srgb(0.95, 0.6, 0.3), 0.0, 0.0, "上釉陶"),
(Color::srgb(0.3, 0.3, 0.3), 0.0, 1.0, "黑橡胶"),
];
let cols = 4;
for (i, &(color, metallic, roughness, _name)) in gallery.iter().enumerate() {
let col = i % cols;
let row = i / cols;
let x = (col as f32 - (cols as f32 - 1.0) / 2.0) * 1.4;
let z = (row as f32 - 1.0) * 1.4;
let mut mat = StandardMaterial {
base_color: color,
metallic,
perceptual_roughness: roughness,
..default()
};
if _name == "上釉陶" {
mat.clearcoat = 1.0;
mat.clearcoat_perceptual_roughness = 0.05;
}
commands.spawn((
Mesh3d(sphere.clone()),
MeshMaterial3d(materials.add(mat)),
Transform::from_xyz(x, 0.5, z),
));
}
commands.spawn((
Mesh3d(meshes.add(Plane3d::default().mesh().size(10.0, 10.0))),
MeshMaterial3d(materials.add(StandardMaterial {
base_color: Color::srgb(0.15, 0.15, 0.15),
perceptual_roughness: 1.0,
..default()
})),
));
commands.spawn((
DirectionalLight {
illuminance: light_consts::lux::FULL_DAYLIGHT,
contact_shadows_enabled: true,
..default()
},
Transform::from_rotation(Quat::from_euler(EulerRot::XYZ, -0.6, 0.4, 0.0)),
));
commands.spawn((
Camera3d::default(),
Transform::from_xyz(4.0, 3.5, 5.5).looking_at(Vec3::new(0.0, 0.2, 0.0), Vec3::Y),
));
}
fn rotate_camera(time: Res<Time>, mut query: Query<&mut Transform, With<Camera3d>>) {
for mut transform in &mut query {
let angle = time.elapsed_secs() * 0.2;
let radius = 6.5;
transform.translation.x = angle.sin() * radius;
transform.translation.z = angle.cos() * radius;
transform.translation.y = 3.5;
*transform = transform.looking_at(Vec3::new(0.0, 0.2, 0.0), Vec3::Y);
}
}Listing 24-8:材质球画廊——十二种现实材质的 PBR 参数组合(examples/listing-24-08.rs)
console
cargo run -p ch24-pbr-materials --example listing-24-08参数速查
| 材质 | base_color | metallic | roughness | 特殊参数 |
|---|---|---|---|---|
| 红漆 | (0.9, 0.1, 0.1) | 0.0 | 0.3 | — |
| 蓝瓷 | (0.1, 0.1, 0.9) | 0.0 | 0.1 | — |
| 黄金 | (1.0, 0.85, 0.0) | 1.0 | 0.2 | — |
| 铬镜 | (0.7, 0.7, 0.7) | 1.0 | 0.05 | — |
| 旧木 | (0.4, 0.25, 0.1) | 0.0 | 0.9 | — |
| 沥青 | (0.15, 0.15, 0.15) | 0.0 | 0.7 | — |
| 白纸 | (0.95, 0.95, 0.95) | 0.0 | 0.5 | — |
| 铜锈 | (0.6, 0.3, 0.1) | 1.0 | 0.6 | — |
| 绿漆 | (0.2, 0.6, 0.3) | 0.0 | 0.4 | — |
| 不锈钢 | (0.8, 0.8, 0.85) | 1.0 | 0.15 | — |
| 上釉陶 | (0.95, 0.6, 0.3) | 0.0 | 0.0 | clearcoat = 1.0 |
| 黑橡胶 | (0.3, 0.3, 0.3) | 0.0 | 1.0 | — |
观察要点:
- 铬镜最暗——和第 21 章的镜面金属一样,没有环境贴图的世界里它照出虚空。给场景加上
EnvironmentMapLight(第 22 章),它会成为最亮的球。 - 铜锈的
metallic = 1.0但roughness = 0.6——它是金属但被锈蚀了,表面粗糙但仍保留金属的有色反射。这正是metallic中间值之外另一种表现"半金属"的方式。 - 上釉陶是本画廊里唯一用了
clearcoat的——底层是粗糙的哑光陶土(roughness = 0.0),上面叠了一层光滑的透明釉。关掉clearcoat试试:它会变成一颗纯色的光滑球,失去"陶土上釉"的层次感。 - 黑橡胶的
roughness = 1.0——完全漫反射,没有高光。现实中橡胶就是这样:不管从哪个角度看,亮度均匀。
画廊里没有 alpha_mode、emissive、specular_transmission 的展品——它们属于特定场景(透明物体、自发光、折射),不适合在"日常材质"的语境下展示。需要时回头查前面各节的 Listing。