Skip to content

Commit aaecde1

Browse files
committed
Add immediate mode example.
1 parent 844d534 commit aaecde1

File tree

9 files changed

+219
-34
lines changed

9 files changed

+219
-34
lines changed

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ path = "examples/lights.rs"
7272
name = "materials"
7373
path = "examples/materials.rs"
7474

75+
[[example]]
76+
name = "pbr"
77+
path = "examples/pbr.rs"
78+
7579
[profile.wasm-release]
7680
inherits = "release"
7781
opt-level = "z"

crates/processing_render/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ use bevy::{
2222
prelude::*,
2323
render::render_resource::{Extent3d, TextureFormat},
2424
};
25-
use render::{activate_cameras, clear_transient_meshes, flush_draw_commands};
2625
use render::material::add_standard_materials;
26+
use render::{activate_cameras, clear_transient_meshes, flush_draw_commands};
2727
use tracing::debug;
2828

2929
use crate::geometry::{AttributeFormat, AttributeValue};

crates/processing_render/src/render/command.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,16 @@ pub enum DrawCommand {
4242
},
4343
Geometry(Entity),
4444
Material(Entity),
45+
Box {
46+
width: f32,
47+
height: f32,
48+
depth: f32,
49+
},
50+
Sphere {
51+
radius: f32,
52+
sectors: u32,
53+
stacks: u32,
54+
},
4555
}
4656

4757
#[derive(Debug, Default, Component)]

crates/processing_render/src/render/material.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,7 @@ impl MaterialKey {
8282

8383
/// A system that adds a `MeshMaterial3d` component to any entity with an `UntypedMaterial` that can
8484
/// be typed as a `StandardMaterial`.
85-
pub fn add_standard_materials(
86-
mut commands: Commands,
87-
meshes: Query<(Entity, &UntypedMaterial)>,
88-
) {
85+
pub fn add_standard_materials(mut commands: Commands, meshes: Query<(Entity, &UntypedMaterial)>) {
8986
for (entity, handle) in meshes.iter() {
9087
let handle = handle.deref().clone();
9188
if let Ok(handle) = handle.try_typed::<StandardMaterial>() {

crates/processing_render/src/render/mod.rs

Lines changed: 97 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use bevy::{
1212
};
1313
use command::{CommandBuffer, DrawCommand};
1414
use material::MaterialKey;
15-
use primitive::{TessellationMode, empty_mesh};
15+
use primitive::{TessellationMode, box_mesh, empty_mesh, sphere_mesh};
1616
use transform::TransformStack;
1717

1818
use crate::{
@@ -124,14 +124,8 @@ pub fn flush_draw_commands(
124124
p_geometries: Query<&Geometry>,
125125
p_material_handles: Query<&UntypedMaterial>,
126126
) {
127-
for (
128-
graphics_entity,
129-
mut cmd_buffer,
130-
mut state,
131-
render_layers,
132-
projection,
133-
camera_transform,
134-
) in graphics.iter_mut()
127+
for (graphics_entity, mut cmd_buffer, mut state, render_layers, projection, camera_transform) in
128+
graphics.iter_mut()
135129
{
136130
let clip_from_view = projection.get_clip_from_view();
137131
let view_from_world = camera_transform.to_matrix().inverse();
@@ -162,9 +156,17 @@ pub fn flush_draw_commands(
162156
}
163157
DrawCommand::Roughness(r) => {
164158
state.material_key = match state.material_key {
165-
MaterialKey::Pbr { albedo, metallic, emissive, .. } => {
166-
MaterialKey::Pbr { albedo, roughness: (r * 255.0) as u8, metallic, emissive }
167-
}
159+
MaterialKey::Pbr {
160+
albedo,
161+
metallic,
162+
emissive,
163+
..
164+
} => MaterialKey::Pbr {
165+
albedo,
166+
roughness: (r * 255.0) as u8,
167+
metallic,
168+
emissive,
169+
},
168170
_ => MaterialKey::Pbr {
169171
albedo: [255, 255, 255, 255],
170172
roughness: (r * 255.0) as u8,
@@ -175,9 +177,17 @@ pub fn flush_draw_commands(
175177
}
176178
DrawCommand::Metallic(m) => {
177179
state.material_key = match state.material_key {
178-
MaterialKey::Pbr { albedo, roughness, emissive, .. } => {
179-
MaterialKey::Pbr { albedo, roughness, metallic: (m * 255.0) as u8, emissive }
180-
}
180+
MaterialKey::Pbr {
181+
albedo,
182+
roughness,
183+
emissive,
184+
..
185+
} => MaterialKey::Pbr {
186+
albedo,
187+
roughness,
188+
metallic: (m * 255.0) as u8,
189+
emissive,
190+
},
181191
_ => MaterialKey::Pbr {
182192
albedo: [255, 255, 255, 255],
183193
roughness: 128,
@@ -189,9 +199,17 @@ pub fn flush_draw_commands(
189199
DrawCommand::Emissive(color) => {
190200
let [r, g, b, a] = color.to_srgba().to_u8_array();
191201
state.material_key = match state.material_key {
192-
MaterialKey::Pbr { albedo, roughness, metallic, .. } => {
193-
MaterialKey::Pbr { albedo, roughness, metallic, emissive: [r, g, b, a] }
194-
}
202+
MaterialKey::Pbr {
203+
albedo,
204+
roughness,
205+
metallic,
206+
..
207+
} => MaterialKey::Pbr {
208+
albedo,
209+
roughness,
210+
metallic,
211+
emissive: [r, g, b, a],
212+
},
195213
_ => MaterialKey::Pbr {
196214
albedo: [255, 255, 255, 255],
197215
roughness: 128,
@@ -287,8 +305,12 @@ pub fn flush_draw_commands(
287305
continue;
288306
};
289307

290-
let Some(mat_handle) = p_material_handles.get(batch.active_material).ok() else {
291-
warn!("Could not find material for entity {:?}", batch.active_material);
308+
let Some(mat_handle) = p_material_handles.get(batch.active_material).ok()
309+
else {
310+
warn!(
311+
"Could not find material for entity {:?}",
312+
batch.active_material
313+
);
292314
continue;
293315
};
294316

@@ -313,6 +335,25 @@ pub fn flush_draw_commands(
313335
batch.active_material = entity;
314336
flush_batch(&mut res, &mut batch);
315337
}
338+
DrawCommand::Box {
339+
width,
340+
height,
341+
depth,
342+
} => {
343+
add_shape3d(&mut res, &mut batch, &state, box_mesh(width, height, depth));
344+
}
345+
DrawCommand::Sphere {
346+
radius,
347+
sectors,
348+
stacks,
349+
} => {
350+
add_shape3d(
351+
&mut res,
352+
&mut batch,
353+
&state,
354+
sphere_mesh(radius, sectors, stacks),
355+
);
356+
}
316357
}
317358
}
318359

@@ -382,11 +423,18 @@ fn start_batch(
382423

383424
fn material_key_with_color(key: &MaterialKey, color: Color) -> MaterialKey {
384425
match key {
385-
MaterialKey::Color { background_image, .. } => MaterialKey::Color {
426+
MaterialKey::Color {
427+
background_image, ..
428+
} => MaterialKey::Color {
386429
transparent: color.alpha() < 1.0,
387430
background_image: background_image.clone(),
388431
},
389-
MaterialKey::Pbr { roughness, metallic, emissive, .. } => {
432+
MaterialKey::Pbr {
433+
roughness,
434+
metallic,
435+
emissive,
436+
..
437+
} => {
390438
let [r, g, b, a] = color.to_srgba().to_u8_array();
391439
MaterialKey::Pbr {
392440
albedo: [r, g, b, a],
@@ -399,6 +447,11 @@ fn material_key_with_color(key: &MaterialKey, color: Color) -> MaterialKey {
399447
}
400448
}
401449

450+
fn material_key_with_fill(state: &RenderState) -> MaterialKey {
451+
let color = state.fill_color.unwrap_or(Color::WHITE);
452+
material_key_with_color(&state.material_key, color)
453+
}
454+
402455
fn add_fill(
403456
res: &mut RenderResources,
404457
batch: &mut BatchState,
@@ -449,6 +502,28 @@ fn flush_batch(res: &mut RenderResources, batch: &mut BatchState) {
449502
batch.material_key = None;
450503
}
451504

505+
fn add_shape3d(res: &mut RenderResources, batch: &mut BatchState, state: &RenderState, mesh: Mesh) {
506+
flush_batch(res, batch);
507+
508+
let mesh_handle = res.meshes.add(mesh);
509+
let material_key = material_key_with_fill(state);
510+
let material_handle = material_key.to_material(&mut res.materials);
511+
512+
let z_offset = -(batch.draw_index as f32 * 0.001);
513+
let mut transform = state.transform.to_bevy_transform();
514+
transform.translation.z += z_offset;
515+
516+
res.commands.spawn((
517+
Mesh3d(mesh_handle),
518+
UntypedMaterial(material_handle),
519+
BelongsToGraphics(batch.graphics_entity),
520+
transform,
521+
batch.render_layers.clone(),
522+
));
523+
524+
batch.draw_index += 1;
525+
}
526+
452527
/// Creates a fullscreen quad by transforming NDC fullscreen by inverse of the clip-from-world matrix
453528
/// so that when the vertex shader applies clip_from_world, the vertices end up correctly back in
454529
/// NDC space.

crates/processing_render/src/render/primitive/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
mod rect;
2+
mod shape3d;
23

34
use bevy::{
45
asset::RenderAssetUsages,
@@ -12,6 +13,7 @@ use lyon::{
1213
},
1314
};
1415
pub use rect::rect;
16+
pub use shape3d::{box_mesh, sphere_mesh};
1517

1618
use super::mesh_builder::MeshBuilder;
1719

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
use bevy::prelude::*;
2+
3+
pub fn box_mesh(width: f32, height: f32, depth: f32) -> Mesh {
4+
let cuboid = bevy::math::primitives::Cuboid::new(width, height, depth);
5+
Mesh::from(cuboid)
6+
}
7+
8+
pub fn sphere_mesh(radius: f32, sectors: u32, stacks: u32) -> Mesh {
9+
let sphere = bevy::math::primitives::Sphere::new(radius);
10+
sphere.mesh().uv(sectors, stacks)
11+
}

examples/materials.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,8 @@ fn sketch() -> error::Result<()> {
3636
transform_set_position(dir_light, 300.0, 400.0, 300.0)?;
3737
transform_look_at(dir_light, 0.0, 0.0, 0.0)?;
3838

39-
let point_light = light_create_point(
40-
graphics,
41-
bevy::color::Color::WHITE,
42-
100_000.0,
43-
800.0,
44-
0.0,
45-
)?;
39+
let point_light =
40+
light_create_point(graphics, bevy::color::Color::WHITE, 100_000.0, 800.0, 0.0)?;
4641
transform_set_position(point_light, 200.0, 200.0, 400.0)?;
4742

4843
// Grid of materials varying roughness (x) and metallic (y)

examples/pbr.rs

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
mod glfw;
2+
3+
use glfw::GlfwContext;
4+
use processing::prelude::*;
5+
use processing_render::render::command::DrawCommand;
6+
7+
fn main() {
8+
match sketch() {
9+
Ok(_) => {
10+
eprintln!("Sketch completed successfully");
11+
exit(0).unwrap();
12+
}
13+
Err(e) => {
14+
eprintln!("Sketch error: {:?}", e);
15+
exit(1).unwrap();
16+
}
17+
};
18+
}
19+
20+
fn sketch() -> error::Result<()> {
21+
let width = 800;
22+
let height = 600;
23+
let mut glfw_ctx = GlfwContext::new(width, height)?;
24+
init(Config::default())?;
25+
26+
let surface = glfw_ctx.create_surface(width, height, 1.0)?;
27+
let graphics = graphics_create(surface, width, height)?;
28+
29+
graphics_mode_3d(graphics)?;
30+
transform_set_position(graphics, 0.0, 0.0, 600.0)?;
31+
transform_look_at(graphics, 0.0, 0.0, 0.0)?;
32+
33+
let dir_light =
34+
light_create_directional(graphics, bevy::color::Color::srgb(1.0, 0.98, 0.95), 1_500.0)?;
35+
transform_set_position(dir_light, 300.0, 400.0, 300.0)?;
36+
transform_look_at(dir_light, 0.0, 0.0, 0.0)?;
37+
38+
let point_light =
39+
light_create_point(graphics, bevy::color::Color::WHITE, 100_000.0, 800.0, 0.0)?;
40+
transform_set_position(point_light, 200.0, 200.0, 400.0)?;
41+
42+
let cols = 11;
43+
let rows = 5;
44+
let base_color = bevy::color::Color::srgb(1.0, 0.85, 0.57);
45+
let spacing = 70.0;
46+
let offset_x = (cols - 1) as f32 * spacing / 2.0;
47+
let offset_y = (rows - 1) as f32 * spacing / 2.0;
48+
49+
while glfw_ctx.poll_events() {
50+
graphics_begin_draw(graphics)?;
51+
52+
graphics_record_command(
53+
graphics,
54+
DrawCommand::BackgroundColor(bevy::color::Color::srgb(0.05, 0.05, 0.07)),
55+
)?;
56+
57+
graphics_record_command(graphics, DrawCommand::Fill(base_color))?;
58+
59+
for row in 0..rows {
60+
for col in 0..cols {
61+
let roughness = col as f32 / (cols - 1) as f32;
62+
let metallic = row as f32 / (rows - 1) as f32;
63+
64+
graphics_record_command(graphics, DrawCommand::Roughness(roughness))?;
65+
graphics_record_command(graphics, DrawCommand::Metallic(metallic))?;
66+
67+
graphics_record_command(graphics, DrawCommand::PushMatrix)?;
68+
graphics_record_command(
69+
graphics,
70+
DrawCommand::Translate {
71+
x: col as f32 * spacing - offset_x,
72+
y: row as f32 * spacing - offset_y,
73+
},
74+
)?;
75+
graphics_record_command(
76+
graphics,
77+
DrawCommand::Sphere {
78+
radius: 30.0,
79+
sectors: 32,
80+
stacks: 18,
81+
},
82+
)?;
83+
graphics_record_command(graphics, DrawCommand::PopMatrix)?;
84+
}
85+
}
86+
87+
graphics_end_draw(graphics)?;
88+
}
89+
90+
Ok(())
91+
}

0 commit comments

Comments
 (0)