Skip to content

Commit 571b4b1

Browse files
committed
Refactor to make MaterialKey enum.
1 parent e17376f commit 571b4b1

File tree

4 files changed

+83
-30
lines changed

4 files changed

+83
-30
lines changed

crates/processing_render/src/lib.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ use tracing::debug;
2525

2626
use crate::geometry::{AttributeFormat, AttributeValue};
2727
use crate::graphics::flush;
28+
use crate::render::material::add_standard_materials;
2829
use crate::{
2930
graphics::GraphicsPlugin, image::ImagePlugin, light::LightPlugin, render::command::DrawCommand,
3031
surface::SurfacePlugin,
@@ -252,7 +253,13 @@ fn create_app(config: Config) -> App {
252253
LightPlugin,
253254
));
254255
app.add_systems(First, (clear_transient_meshes, activate_cameras))
255-
.add_systems(Update, flush_draw_commands.before(AssetEventSystems));
256+
.add_systems(
257+
Update,
258+
(
259+
flush_draw_commands.before(AssetEventSystems),
260+
add_standard_materials.after(flush_draw_commands),
261+
),
262+
);
256263

257264
app
258265
}
Lines changed: 59 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,68 @@
1+
use std::ops::Deref;
12
use bevy::{prelude::*, render::alpha::AlphaMode};
23

4+
/// A component that holds an untyped handle to a material. This allows the main render loop
5+
/// to be agnostic of the specific material types being used, and allows for dynamic material
6+
/// creation based on the `MaterialKey`.
7+
#[derive(Component, Deref)]
8+
pub struct UntypedMaterial(pub UntypedHandle);
9+
10+
/// Defines the current material for a batch, which can be used to determine when to flush the
11+
/// current batch and start a new one.
312
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
4-
pub struct MaterialKey {
5-
pub transparent: bool,
6-
pub background_image: Option<Handle<Image>>,
13+
pub enum MaterialKey {
14+
Color {
15+
transparent: bool,
16+
background_image: Option<Handle<Image>>,
17+
},
18+
Pbr {},
19+
Custom(Entity),
720
}
821

922
impl MaterialKey {
10-
pub fn to_material(&self) -> StandardMaterial {
11-
StandardMaterial {
12-
base_color: Color::WHITE,
13-
unlit: true,
14-
cull_mode: None,
15-
base_color_texture: self.background_image.clone(),
16-
alpha_mode: if self.transparent {
17-
AlphaMode::Blend
18-
} else {
19-
AlphaMode::Opaque
20-
},
21-
..default()
23+
pub fn to_material(
24+
&self,
25+
standard_materials: &mut ResMut<Assets<StandardMaterial>>,
26+
) -> UntypedHandle {
27+
match self {
28+
MaterialKey::Color {
29+
background_image,
30+
transparent,
31+
} => {
32+
let mat = StandardMaterial {
33+
base_color: Color::WHITE,
34+
unlit: true,
35+
cull_mode: None,
36+
base_color_texture: background_image.clone(),
37+
alpha_mode: if *transparent {
38+
AlphaMode::Blend
39+
} else {
40+
AlphaMode::Opaque
41+
},
42+
..default()
43+
};
44+
standard_materials.add(mat).untyped()
45+
}
46+
MaterialKey::Pbr { .. } => {
47+
todo!("implement pbr materials")
48+
}
49+
MaterialKey::Custom(_) => {
50+
todo!("implement custom materials")
51+
}
52+
}
53+
}
54+
}
55+
56+
/// A system that adds a `MeshMaterial3d` component to any entity with an `UntypedMaterial` that can
57+
/// be typed as a `StandardMaterial`.
58+
pub(crate) fn add_standard_materials(
59+
mut commands: Commands,
60+
meshes: Query<(Entity, &UntypedMaterial)>,
61+
) {
62+
for (entity, handle) in meshes.iter() {
63+
let handle = handle.deref().clone();
64+
if let Ok(handle) = handle.try_typed::<StandardMaterial>() {
65+
commands.entity(entity).insert(MeshMaterial3d(handle));
2266
}
2367
}
2468
}

crates/processing_render/src/render/mod.rs

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use primitive::{TessellationMode, empty_mesh};
1616
use transform::TransformStack;
1717

1818
use crate::{Flush, geometry::Geometry, image::Image, render::primitive::rect};
19+
use crate::render::material::UntypedMaterial;
1920

2021
#[derive(Component)]
2122
#[relationship(relationship_target = TransientMeshes)]
@@ -153,15 +154,15 @@ pub fn flush_draw_commands(
153154
let mesh = create_ndc_background_quad(world_from_clip, color, false);
154155
let mesh_handle = res.meshes.add(mesh);
155156

156-
let material_key = MaterialKey {
157+
let material_key = MaterialKey::Color {
157158
transparent: color.alpha() < 1.0,
158159
background_image: None,
159160
};
160-
let material_handle = res.materials.add(material_key.to_material());
161+
let material_handle = material_key.to_material(&mut res.materials);
161162

162163
res.commands.spawn((
163164
Mesh3d(mesh_handle),
164-
MeshMaterial3d(material_handle),
165+
UntypedMaterial(material_handle),
165166
BelongsToGraphics(batch.graphics_entity),
166167
Transform::IDENTITY,
167168
batch.render_layers.clone(),
@@ -180,15 +181,15 @@ pub fn flush_draw_commands(
180181
let mesh = create_ndc_background_quad(world_from_clip, Color::WHITE, true);
181182
let mesh_handle = res.meshes.add(mesh);
182183

183-
let material_key = MaterialKey {
184+
let material_key = MaterialKey::Color {
184185
transparent: false,
185186
background_image: Some(p_image.handle.clone()),
186187
};
187-
let material_handle = res.materials.add(material_key.to_material());
188+
let material_handle = material_key.to_material(&mut res.materials);
188189

189190
res.commands.spawn((
190191
Mesh3d(mesh_handle),
191-
MeshMaterial3d(material_handle),
192+
UntypedMaterial(material_handle),
192193
BelongsToGraphics(batch.graphics_entity),
193194
Transform::IDENTITY,
194195
batch.render_layers.clone(),
@@ -214,20 +215,20 @@ pub fn flush_draw_commands(
214215

215216
// TODO: Implement state based material API
216217
// https://github.com/processing/libprocessing/issues/10
217-
let material_key = MaterialKey {
218+
let material_key = MaterialKey::Color {
218219
transparent: false, // TODO: detect from geometry colors
219220
background_image: None,
220221
};
221222

222-
let material_handle = res.materials.add(material_key.to_material());
223+
let material_handle = material_key.to_material(&mut res.materials);
223224
let z_offset = -(batch.draw_index as f32 * 0.001);
224225

225226
let mut transform = state.transform.to_bevy_transform();
226227
transform.translation.z += z_offset;
227228

228229
res.commands.spawn((
229230
Mesh3d(geometry.handle.clone()),
230-
MeshMaterial3d(material_handle),
231+
UntypedMaterial(material_handle),
231232
BelongsToGraphics(batch.graphics_entity),
232233
transform,
233234
batch.render_layers.clone(),
@@ -265,7 +266,7 @@ fn spawn_mesh(res: &mut RenderResources, batch: &mut BatchState, mesh: Mesh, z_o
265266
};
266267

267268
let mesh_handle = res.meshes.add(mesh);
268-
let material_handle = res.materials.add(material_key.to_material());
269+
let material_handle = material_key.to_material(&mut res.materials);
269270

270271
let (scale, rotation, translation) = batch.transform.to_scale_rotation_translation();
271272
let transform = Transform {
@@ -276,7 +277,7 @@ fn spawn_mesh(res: &mut RenderResources, batch: &mut BatchState, mesh: Mesh, z_o
276277

277278
res.commands.spawn((
278279
Mesh3d(mesh_handle),
279-
MeshMaterial3d(material_handle),
280+
UntypedMaterial(material_handle),
280281
BelongsToGraphics(batch.graphics_entity),
281282
transform,
282283
batch.render_layers.clone(),
@@ -311,8 +312,8 @@ fn add_fill(
311312
let Some(color) = state.fill_color else {
312313
return;
313314
};
314-
let material_key = MaterialKey {
315-
transparent: state.fill_is_transparent(),
315+
let material_key = MaterialKey::Color {
316+
transparent: state.fill_is_transparent(),
316317
background_image: None,
317318
};
318319

@@ -335,7 +336,7 @@ fn add_stroke(
335336
return;
336337
};
337338
let stroke_weight = state.stroke_weight;
338-
let material_key = MaterialKey {
339+
let material_key = MaterialKey::Color {
339340
transparent: state.stroke_is_transparent(),
340341
background_image: None,
341342
};

crates/processing_render/src/surface.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
//! - WebAssembly: `create_surface_web`
2020
#[cfg(any(target_os = "linux", target_arch = "wasm32"))]
2121
use std::ffi::c_void;
22+
#[cfg(not(target_os = "windows"))]
2223
use std::ptr::NonNull;
2324

2425
use bevy::{

0 commit comments

Comments
 (0)