|
| 1 | +//! Demonstrates how to use transparency in 3D. |
| 2 | +//! Shows the effects of different blend modes. |
| 3 | +//! The `fade_transparency` system smoothly changes the transparency over time. |
| 4 | +
|
| 5 | +use bevy::prelude::*; |
| 6 | + |
| 7 | +fn main() { |
| 8 | + App::new() |
| 9 | + .insert_resource(Msaa { samples: 4 }) |
| 10 | + .add_plugins(DefaultPlugins) |
| 11 | + .add_startup_system(setup) |
| 12 | + .add_system(fade_transparency) |
| 13 | + .run(); |
| 14 | +} |
| 15 | + |
| 16 | +#[derive(Component)] |
| 17 | +pub struct FadeTransparency; |
| 18 | + |
| 19 | +fn setup( |
| 20 | + mut commands: Commands, |
| 21 | + mut meshes: ResMut<Assets<Mesh>>, |
| 22 | + mut materials: ResMut<Assets<StandardMaterial>>, |
| 23 | +) { |
| 24 | + // Opaque plane |
| 25 | + commands.spawn_bundle(PbrBundle { |
| 26 | + mesh: meshes.add(Mesh::from(shape::Plane { size: 6.0 })), |
| 27 | + material: materials.add(Color::rgb(0.3, 0.5, 0.3).into()), |
| 28 | + ..Default::default() |
| 29 | + }); |
| 30 | + // transparent sphere, using alpha_mode: Mask |
| 31 | + commands.spawn_bundle(PbrBundle { |
| 32 | + mesh: meshes.add(Mesh::from(shape::Icosphere { |
| 33 | + radius: 0.5, |
| 34 | + subdivisions: 3, |
| 35 | + })), |
| 36 | + material: materials.add(StandardMaterial { |
| 37 | + // Alpha channel of the color controls transparency. |
| 38 | + // We set it to 0.0 here, because it will be changed over time in the |
| 39 | + // `fade_transparency` function. |
| 40 | + // Note that the transparency has no effect on the objects shadow. |
| 41 | + base_color: Color::rgba(0.2, 0.7, 0.1, 0.0), |
| 42 | + // Maks sets a cutoff for transparency. Alpha values below are fully transparent, |
| 43 | + // alpha values above are fully opaque. |
| 44 | + alpha_mode: AlphaMode::Mask(0.5), |
| 45 | + ..default() |
| 46 | + }), |
| 47 | + transform: Transform::from_xyz(1.0, 0.5, -1.5), |
| 48 | + ..Default::default() |
| 49 | + }); |
| 50 | + // transparent cube, using alpha_mode: Blend |
| 51 | + commands.spawn_bundle(PbrBundle { |
| 52 | + mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })), |
| 53 | + // Notice how there is no need to set the `alpha_mode` explicitly here. |
| 54 | + // When converting a color to a material using `into()`, the alpha mode is |
| 55 | + // automatically set to `Blend` if the alpha channel is anything lower than 1.0. |
| 56 | + material: materials.add(Color::rgba(0.5, 0.5, 1.0, 0.0).into()), |
| 57 | + transform: Transform::from_xyz(0.0, 0.5, 0.0), |
| 58 | + ..Default::default() |
| 59 | + }); |
| 60 | + // sphere |
| 61 | + commands.spawn_bundle(PbrBundle { |
| 62 | + mesh: meshes.add(Mesh::from(shape::Icosphere { |
| 63 | + radius: 0.5, |
| 64 | + subdivisions: 3, |
| 65 | + })), |
| 66 | + material: materials.add(Color::rgb(0.7, 0.2, 0.1).into()), |
| 67 | + transform: Transform::from_xyz(0.0, 0.5, -1.5), |
| 68 | + ..Default::default() |
| 69 | + }); |
| 70 | + // light |
| 71 | + commands.spawn_bundle(PointLightBundle { |
| 72 | + point_light: PointLight { |
| 73 | + intensity: 1500.0, |
| 74 | + shadows_enabled: true, |
| 75 | + ..Default::default() |
| 76 | + }, |
| 77 | + transform: Transform::from_xyz(4.0, 8.0, 4.0), |
| 78 | + ..Default::default() |
| 79 | + }); |
| 80 | + // camera |
| 81 | + commands.spawn_bundle(Camera3dBundle { |
| 82 | + transform: Transform::from_xyz(-2.0, 3.0, 5.0).looking_at(Vec3::ZERO, Vec3::Y), |
| 83 | + ..Default::default() |
| 84 | + }); |
| 85 | +} |
| 86 | + |
| 87 | +/// Fades the alpha channel of all materials between 0 and 1 over time. |
| 88 | +/// Each blend mode responds differently to this: |
| 89 | +/// - `Opaque`: Ignores alpha channel altogether, these materials stay completely opaque. |
| 90 | +/// - `Mask(f32)`: Object appears when the alpha value goes above the mask's threshold, disappears |
| 91 | +/// when the alpha value goes back below the threshold. |
| 92 | +/// - `Blend`: Object fades in and out smoothly. |
| 93 | +pub fn fade_transparency(time: Res<Time>, mut materials: ResMut<Assets<StandardMaterial>>) { |
| 94 | + let alpha = (time.time_since_startup().as_secs_f32().sin() / 2.0) + 0.5; |
| 95 | + for (_, material) in materials.iter_mut() { |
| 96 | + material.base_color.set_a(alpha); |
| 97 | + } |
| 98 | +} |
0 commit comments