docs/bevy/examples/3d/wireframe.rs 6.9 K · 219 lines · raw · history

1 //! Showcases wireframe rendering.
2 //!
3 //! Wireframes currently do not work when using webgl or webgpu.
4 //! Supported platforms:
5 //! - DX12
6 //! - Vulkan
7 //! - Metal
8 //!
9 //! This is a native only feature.
10
11 use bevy::{
12 color::palettes::css::*,
13 pbr::wireframe::{
14 NoWireframe, Wireframe, WireframeColor, WireframeConfig, WireframeLineWidth,
15 WireframePlugin, WireframeTopology, WireframeXray,
16 },
17 prelude::*,
18 render::{render_resource::WgpuFeatures, settings::WgpuSettings, RenderPlugin},
19 };
20
21 fn main() {
22 App::new()
23 .add_plugins((
24 DefaultPlugins.set(RenderPlugin {
25 render_creation: WgpuSettings {
26 // WARN this is a native only feature. It will not work with webgl or webgpu
27 features: WgpuFeatures::POLYGON_MODE_LINE,
28 ..default()
29 }
30 .into(),
31 ..default()
32 }),
33 // You need to add this plugin to enable wireframe rendering
34 WireframePlugin::default(),
35 ))
36 // Wireframes can be configured with this resource. This can be changed at runtime.
37 .insert_resource(WireframeConfig {
38 // The global wireframe config enables drawing of wireframes on every mesh,
39 // except those with `NoWireframe`. Meshes with `Wireframe` will always have a wireframe,
40 // regardless of the global configuration.
41 global: true,
42 // Controls the default color of all wireframes. Used as the default color for global wireframes.
43 // Can be changed per mesh using the `WireframeColor` component.
44 default_color: WHITE.into(),
45 xray_mode: false,
46 ..default()
47 })
48 .add_systems(Startup, setup)
49 .add_systems(Update, update_colors)
50 .run();
51 }
52
53 #[derive(Component)]
54 struct ColorToggleCube;
55
56 /// set up a simple 3D scene
57 fn setup(
58 mut commands: Commands,
59 mut meshes: ResMut<Assets<Mesh>>,
60 mut materials: ResMut<Assets<StandardMaterial>>,
61 ) {
62 // Red cube: Never renders a wireframe
63 commands.spawn((
64 Mesh3d(meshes.add(Cuboid::default())),
65 MeshMaterial3d(materials.add(Color::from(RED))),
66 Transform::from_xyz(-1.5, 0.5, -1.5),
67 NoWireframe,
68 ));
69 // Orange cube: Follows global wireframe setting
70 commands.spawn((
71 Mesh3d(meshes.add(Cuboid::default())),
72 MeshMaterial3d(materials.add(Color::from(ORANGE))),
73 Transform::from_xyz(-0.5, 0.5, -0.5),
74 ));
75 // Green cube: Always renders a wireframe with custom color
76 commands.spawn((
77 Mesh3d(meshes.add(Cuboid::default())),
78 MeshMaterial3d(materials.add(Color::from(LIME))),
79 Transform::from_xyz(0.5, 0.5, 0.5),
80 Wireframe,
81 // This lets you configure the wireframe color of this entity.
82 // If not set, this will use the color in `WireframeConfig`
83 WireframeColor { color: LIME.into() },
84 WireframeXray(false),
85 ColorToggleCube,
86 ));
87
88 // Purple cube: wireframe with explicit Quads topology override
89 commands.spawn((
90 Mesh3d(meshes.add(Cuboid::default())),
91 MeshMaterial3d(materials.add(Color::from(PURPLE))),
92 Transform::from_xyz(1.5, 0.5, 1.5),
93 Wireframe,
94 WireframeColor {
95 color: YELLOW.into(),
96 },
97 WireframeLineWidth { width: 3.0 },
98 WireframeTopology::Quads,
99 ));
100
101 // plane
102 commands.spawn((
103 Mesh3d(meshes.add(Plane3d::default().mesh().size(5.0, 5.0))),
104 MeshMaterial3d(materials.add(Color::from(BLUE))),
105 // You can insert this component without the `Wireframe` component
106 // to override the color of the global wireframe for this mesh
107 WireframeColor {
108 color: BLACK.into(),
109 },
110 ));
111
112 // light
113 commands.spawn((PointLight::default(), Transform::from_xyz(2.0, 4.0, 2.0)));
114
115 // camera
116 commands.spawn((
117 Camera3d::default(),
118 Transform::from_xyz(-2.0, 2.5, 5.0).looking_at(Vec3::ZERO, Vec3::Y),
119 ));
120
121 // Text used to show controls
122 commands.spawn((
123 Text::default(),
124 Node {
125 position_type: PositionType::Absolute,
126 top: px(12),
127 left: px(12),
128 ..default()
129 },
130 ));
131 }
132
133 /// This system let's you toggle various wireframe settings
134 fn update_colors(
135 keyboard_input: Res<ButtonInput<KeyCode>>,
136 mut config: ResMut<WireframeConfig>,
137 mut wireframe_colors: Query<&mut WireframeColor, With<ColorToggleCube>>,
138 mut xray_cubes: Query<&mut WireframeXray, With<ColorToggleCube>>,
139 mut wireframe_widths: Query<&mut WireframeLineWidth>,
140 mut text: Single<&mut Text>,
141 ) {
142 let current_width = wireframe_widths
143 .iter()
144 .next()
145 .map(|w| w.width)
146 .unwrap_or(1.0);
147 let green_cube_xray = xray_cubes.iter().any(|xray| xray.0);
148
149 text.0 = format!(
150 "Controls
151 ---------------
152 Z - Toggle global
153 X - Change global color
154 C - Change color of the green cube wireframe
155 V - Line width (current: {current_width:.1}px)
156 B - Toggle topology (current: {:?})
157 N - Toggle global x-ray mode (current: {:?})
158 M - Toggle x-ray mode for the green cube (current: {green_cube_xray})
159
160 WireframeConfig
161 -------------
162 Global: {}
163 Color: {:?}",
164 config.default_topology, config.xray_mode, config.global, config.default_color,
165 );
166
167 // Toggle showing a wireframe on all meshes
168 if keyboard_input.just_pressed(KeyCode::KeyZ) {
169 config.global = !config.global;
170 }
171
172 // Toggle the global wireframe color
173 if keyboard_input.just_pressed(KeyCode::KeyX) {
174 config.default_color = if config.default_color == WHITE.into() {
175 DEEP_PINK.into()
176 } else {
177 WHITE.into()
178 };
179 }
180
181 // Toggle the color of a wireframe using WireframeColor and not the global color
182 if keyboard_input.just_pressed(KeyCode::KeyC) {
183 for mut color in &mut wireframe_colors {
184 color.color = if color.color == LIME.into() {
185 RED.into()
186 } else {
187 LIME.into()
188 };
189 }
190 }
191
192 if keyboard_input.just_pressed(KeyCode::KeyV) {
193 for mut width in &mut wireframe_widths {
194 width.width = match width.width as u32 {
195 0..=2 => 3.0,
196 3..=4 => 5.0,
197 5..=7 => 10.0,
198 _ => 2.0,
199 };
200 }
201 }
202
203 if keyboard_input.just_pressed(KeyCode::KeyB) {
204 config.default_topology = match config.default_topology {
205 WireframeTopology::Triangles => WireframeTopology::Quads,
206 WireframeTopology::Quads => WireframeTopology::Triangles,
207 };
208 }
209
210 if keyboard_input.just_pressed(KeyCode::KeyN) {
211 config.xray_mode = !config.xray_mode;
212 }
213
214 if keyboard_input.just_pressed(KeyCode::KeyM) {
215 for mut xray in &mut xray_cubes {
216 xray.0 = !xray.0;
217 }
218 }
219 }