order_independent_transparency/
order_independent_transparency.rs1use bevy::{
7 camera::visibility::RenderLayers,
8 color::palettes::css::{BLUE, GREEN, RED, YELLOW},
9 core_pipeline::{oit::OrderIndependentTransparencySettings, prepass::DepthPrepass},
10 prelude::*,
11};
12
13fn main() {
14 App::new()
15 .add_plugins(DefaultPlugins)
16 .add_systems(Startup, setup)
17 .add_systems(Update, (toggle_oit, cycle_scenes))
18 .run();
19}
20
21fn setup(
23 mut commands: Commands,
24 mut meshes: ResMut<Assets<Mesh>>,
25 mut materials: ResMut<Assets<StandardMaterial>>,
26) {
27 commands.spawn((
29 Camera3d::default(),
30 Transform::from_xyz(0.0, 0.0, 10.0).looking_at(Vec3::ZERO, Vec3::Y),
31 OrderIndependentTransparencySettings::default(),
33 RenderLayers::layer(1),
34 Msaa::Off,
36 DepthPrepass,
38 ));
39
40 commands.spawn((
42 PointLight {
43 shadow_maps_enabled: false,
44 ..default()
45 },
46 Transform::from_xyz(4.0, 8.0, 4.0),
47 RenderLayers::layer(1),
48 ));
49
50 commands.spawn((
52 Text::default(),
53 Node {
54 position_type: PositionType::Absolute,
55 top: px(12),
56 left: px(12),
57 ..default()
58 },
59 RenderLayers::layer(1),
60 children![
61 TextSpan::new("Press T to toggle OIT\n"),
62 TextSpan::new("OIT Enabled"),
63 TextSpan::new("\nPress C to cycle test scenes"),
64 ],
65 ));
66
67 spawn_spheres(&mut commands, &mut meshes, &mut materials);
69}
70
71fn toggle_oit(
72 mut commands: Commands,
73 text: Single<Entity, With<Text>>,
74 keyboard_input: Res<ButtonInput<KeyCode>>,
75 q: Single<(Entity, Has<OrderIndependentTransparencySettings>), With<Camera3d>>,
76 mut text_writer: TextUiWriter,
77) {
78 if keyboard_input.just_pressed(KeyCode::KeyT) {
79 let (e, has_oit) = *q;
80 *text_writer.text(*text, 2) = if has_oit {
81 commands
83 .entity(e)
84 .remove::<OrderIndependentTransparencySettings>();
85 "OIT disabled".to_string()
86 } else {
87 commands
90 .entity(e)
91 .insert(OrderIndependentTransparencySettings::default());
92 "OIT enabled".to_string()
93 };
94 }
95}
96
97fn cycle_scenes(
98 mut commands: Commands,
99 keyboard_input: Res<ButtonInput<KeyCode>>,
100 mut meshes: ResMut<Assets<Mesh>>,
101 mut materials: ResMut<Assets<StandardMaterial>>,
102 q: Query<Entity, With<Mesh3d>>,
103 mut scene_id: Local<usize>,
104 asset_server: Res<AssetServer>,
105) {
106 if keyboard_input.just_pressed(KeyCode::KeyC) {
107 for e in &q {
109 commands.entity(e).despawn();
110 }
111 *scene_id = (*scene_id + 1) % 4;
113 match *scene_id {
115 0 => spawn_spheres(&mut commands, &mut meshes, &mut materials),
116 1 => spawn_quads(&mut commands, &mut meshes, &mut materials),
117 2 => spawn_occlusion_test(&mut commands, &mut meshes, &mut materials),
118 3 => {
119 spawn_auto_instancing_test(
120 &mut commands,
121 &mut meshes,
122 &mut materials,
123 asset_server,
124 );
125 }
126 _ => unreachable!(),
127 }
128 }
129}
130
131fn spawn_spheres(
135 commands: &mut Commands,
136 meshes: &mut Assets<Mesh>,
137 materials: &mut Assets<StandardMaterial>,
138) {
139 let pos_a = Vec3::new(-1.0, 0.75, 0.0);
140 let pos_b = Vec3::new(0.0, -0.75, 0.0);
141 let pos_c = Vec3::new(1.0, 0.75, 0.0);
142
143 let offset = Vec3::new(0.0, 0.0, 0.0);
144
145 let sphere_handle = meshes.add(Sphere::new(2.0).mesh());
146
147 let alpha = 0.25;
148
149 let render_layers = RenderLayers::layer(1);
150
151 commands.spawn((
152 Mesh3d(sphere_handle.clone()),
153 MeshMaterial3d(materials.add(StandardMaterial {
154 base_color: RED.with_alpha(alpha).into(),
155 alpha_mode: AlphaMode::Blend,
156 ..default()
157 })),
158 Transform::from_translation(pos_a + offset),
159 render_layers.clone(),
160 ));
161 commands.spawn((
162 Mesh3d(sphere_handle.clone()),
163 MeshMaterial3d(materials.add(StandardMaterial {
164 base_color: GREEN.with_alpha(alpha).into(),
165 alpha_mode: AlphaMode::Blend,
166 ..default()
167 })),
168 Transform::from_translation(pos_b + offset),
169 render_layers.clone(),
170 ));
171 commands.spawn((
172 Mesh3d(sphere_handle.clone()),
173 MeshMaterial3d(materials.add(StandardMaterial {
174 base_color: BLUE.with_alpha(alpha).into(),
175 alpha_mode: AlphaMode::Blend,
176 ..default()
177 })),
178 Transform::from_translation(pos_c + offset),
179 render_layers.clone(),
180 ));
181}
182
183fn spawn_quads(
184 commands: &mut Commands,
185 meshes: &mut Assets<Mesh>,
186 materials: &mut Assets<StandardMaterial>,
187) {
188 let quad_handle = meshes.add(Rectangle::new(3.0, 3.0).mesh());
189 let render_layers = RenderLayers::layer(1);
190 let xform = |x, y, z| {
191 Transform::from_rotation(Quat::from_rotation_y(0.5))
192 .mul_transform(Transform::from_xyz(x, y, z))
193 };
194 commands.spawn((
195 Mesh3d(quad_handle.clone()),
196 MeshMaterial3d(materials.add(StandardMaterial {
197 base_color: RED.with_alpha(0.5).into(),
198 alpha_mode: AlphaMode::Blend,
199 ..default()
200 })),
201 xform(1.0, -0.1, 0.),
202 render_layers.clone(),
203 ));
204 commands.spawn((
205 Mesh3d(quad_handle.clone()),
206 MeshMaterial3d(materials.add(StandardMaterial {
207 base_color: BLUE.with_alpha(0.8).into(),
208 alpha_mode: AlphaMode::Blend,
209 ..default()
210 })),
211 xform(0.5, 0.2, -0.5),
212 render_layers.clone(),
213 ));
214 commands.spawn((
215 Mesh3d(quad_handle.clone()),
216 MeshMaterial3d(materials.add(StandardMaterial {
217 base_color: GREEN.with_green(1.0).with_alpha(0.5).into(),
218 alpha_mode: AlphaMode::Blend,
219 ..default()
220 })),
221 xform(0.0, 0.4, -1.),
222 render_layers.clone(),
223 ));
224 commands.spawn((
225 Mesh3d(quad_handle.clone()),
226 MeshMaterial3d(materials.add(StandardMaterial {
227 base_color: YELLOW.with_alpha(0.3).into(),
228 alpha_mode: AlphaMode::Blend,
229 ..default()
230 })),
231 xform(-0.5, 0.6, -1.1),
232 render_layers.clone(),
233 ));
234 commands.spawn((
235 Mesh3d(quad_handle.clone()),
236 MeshMaterial3d(materials.add(StandardMaterial {
237 base_color: BLUE.with_alpha(0.2).into(),
238 alpha_mode: AlphaMode::Blend,
239 ..default()
240 })),
241 xform(-0.8, 0.8, -1.2),
242 render_layers.clone(),
243 ));
244}
245
246fn spawn_occlusion_test(
250 commands: &mut Commands,
251 meshes: &mut Assets<Mesh>,
252 materials: &mut Assets<StandardMaterial>,
253) {
254 let sphere_handle = meshes.add(Sphere::new(1.0).mesh());
255 let cube_handle = meshes.add(Cuboid::from_size(Vec3::ONE).mesh());
256 let cube_material = materials.add(Color::srgb(0.8, 0.7, 0.6));
257
258 let render_layers = RenderLayers::layer(1);
259
260 let x = -2.5;
262 commands.spawn((
263 Mesh3d(cube_handle.clone()),
264 MeshMaterial3d(cube_material.clone()),
265 Transform::from_xyz(x, 0.0, 2.0),
266 render_layers.clone(),
267 ));
268 commands.spawn((
269 Mesh3d(sphere_handle.clone()),
270 MeshMaterial3d(materials.add(StandardMaterial {
271 base_color: RED.with_alpha(0.5).into(),
272 alpha_mode: AlphaMode::Blend,
273 ..default()
274 })),
275 Transform::from_xyz(x, 0., 0.),
276 render_layers.clone(),
277 ));
278
279 commands.spawn((
281 Mesh3d(cube_handle.clone()),
282 MeshMaterial3d(cube_material.clone()),
283 Transform::from_xyz(x, 0.0, 1.0),
284 render_layers.clone(),
285 ));
286 commands.spawn((
287 Mesh3d(sphere_handle.clone()),
288 MeshMaterial3d(materials.add(StandardMaterial {
289 base_color: RED.with_alpha(0.5).into(),
290 alpha_mode: AlphaMode::Blend,
291 ..default()
292 })),
293 Transform::from_xyz(0., 0., 0.),
294 render_layers.clone(),
295 ));
296
297 let x = 2.5;
299 commands.spawn((
300 Mesh3d(cube_handle.clone()),
301 MeshMaterial3d(cube_material.clone()),
302 Transform::from_xyz(x, 0.0, -2.0),
303 render_layers.clone(),
304 ));
305 commands.spawn((
306 Mesh3d(sphere_handle.clone()),
307 MeshMaterial3d(materials.add(StandardMaterial {
308 base_color: RED.with_alpha(0.5).into(),
309 alpha_mode: AlphaMode::Blend,
310 ..default()
311 })),
312 Transform::from_xyz(x, 0., 0.),
313 render_layers.clone(),
314 ));
315}
316
317fn spawn_auto_instancing_test(
318 commands: &mut Commands,
319 meshes: &mut Assets<Mesh>,
320 materials: &mut Assets<StandardMaterial>,
321 asset_server: Res<AssetServer>,
322) {
323 let render_layers = RenderLayers::layer(1);
324
325 let cube = meshes.add(Cuboid::new(1.0, 1.0, 1.0));
326 let material_handle = materials.add(StandardMaterial {
327 alpha_mode: AlphaMode::Blend,
328 base_color_texture: Some(asset_server.load("textures/slice_square.png")),
329 ..Default::default()
330 });
331 let mut bundles = Vec::with_capacity(3 * 3 * 3);
332
333 for z in -1..=1 {
334 for y in -1..=1 {
335 for x in -1..=1 {
336 bundles.push((
337 Mesh3d(cube.clone()),
338 MeshMaterial3d(material_handle.clone()),
339 Transform::from_xyz(x as f32 * 2.0, y as f32 * 2.0, z as f32 * 2.0),
340 render_layers.clone(),
341 ));
342 }
343 }
344 }
345 commands.spawn_batch(bundles);
346}