Skip to content

Commit f2b5a21

Browse files
committed
Clean up.
1 parent 7c98623 commit f2b5a21

File tree

9 files changed

+21
-154
lines changed

9 files changed

+21
-154
lines changed

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,8 @@ name = "gltf_load"
9090
path = "examples/gltf_load.rs"
9191

9292
[[example]]
93-
name = "custom_shader"
94-
path = "examples/custom_shader.rs"
93+
name = "custom_material"
94+
path = "examples/custom_material.rs"
9595

9696
[profile.wasm-release]
9797
inherits = "release"
File renamed without changes.

crates/processing_pyo3/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,7 @@ fn push_matrix(module: &Bound<'_, PyModule>) -> PyResult<()> {
371371
#[pyfunction]
372372
#[pyo3(pass_module)]
373373
fn pop_matrix(module: &Bound<'_, PyModule>) -> PyResult<()> {
374-
graphics!(module).push_matrix()
374+
graphics!(module).pop_matrix()
375375
}
376376

377377
#[pyfunction]

crates/processing_pyo3/src/material.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ impl Material {
4444
kwargs: Option<&Bound<'_, PyDict>>,
4545
) -> PyResult<Self> {
4646
let entity = if vertex.is_some() || fragment.is_some() {
47-
material_create_from_shaders(
47+
material_create_custom(
4848
vertex.map(|s| s.entity),
4949
fragment.map(|s| s.entity),
5050
)

crates/processing_render/src/graphics.rs

Lines changed: 0 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -457,8 +457,6 @@ pub fn flush(app: &mut App, entity: Entity) -> Result<()> {
457457
Ok(())
458458
}
459459

460-
/// Present the current frame to the surface. Flushes any pending draw commands,
461-
/// enables camera output for one frame, then disables it again.
462460
pub fn present(app: &mut App, entity: Entity) -> Result<()> {
463461
graphics_mut!(app, entity)
464462
.get_mut::<Camera>()
@@ -473,41 +471,6 @@ pub fn present(app: &mut App, entity: Entity) -> Result<()> {
473471
.ok_or(ProcessingError::GraphicsNotFound)?
474472
.output_mode = CameraOutputMode::Skip;
475473

476-
// // Sync ViewTarget textures: copy main_texture → main_texture_other.
477-
// // This ensures both A and B have identical content regardless of whether
478-
// // post-processing effects called post_process_write() (which swaps A/B).
479-
// app.world_mut()
480-
// .run_system_cached_with(sync_view_target_textures, entity)
481-
// .unwrap()?;
482-
483-
Ok(())
484-
}
485-
486-
/// Copy the current main_texture to main_texture_other so both ViewTarget
487-
/// textures have identical content. This ensures pixel persistence works
488-
/// regardless of post-processing effects that may swap the A/B texture selector.
489-
fn sync_view_target_textures(
490-
In(entity): In<Entity>,
491-
graphics_query: Query<&Graphics>,
492-
graphics_targets: Res<GraphicsTargets>,
493-
render_device: Res<RenderDevice>,
494-
render_queue: Res<RenderQueue>,
495-
) -> Result<()> {
496-
let graphics = graphics_query
497-
.get(entity)
498-
.map_err(|_| ProcessingError::GraphicsNotFound)?;
499-
500-
let view_target = graphics_targets
501-
.get(&entity)
502-
.ok_or(ProcessingError::GraphicsNotFound)?;
503-
504-
let src = view_target.main_texture();
505-
let dst = view_target.main_texture_other();
506-
507-
let mut encoder = render_device.create_command_encoder(&CommandEncoderDescriptor::default());
508-
encoder.copy_texture_to_texture(src.as_image_copy(), dst.as_image_copy(), graphics.size);
509-
render_queue.submit(std::iter::once(encoder.finish()));
510-
511474
Ok(())
512475
}
513476

@@ -528,7 +491,6 @@ pub fn record_command(
528491
Ok(())
529492
}
530493

531-
/// Raw readback result containing bytes and format metadata.
532494
pub struct ReadbackData {
533495
pub bytes: Vec<u8>,
534496
pub format: TextureFormat,

crates/processing_render/src/lib.rs

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1327,21 +1327,13 @@ pub fn shader_destroy(entity: Entity) -> error::Result<()> {
13271327
})
13281328
}
13291329

1330-
pub fn material_create_from_shaders(
1330+
pub fn material_create_custom(
13311331
vertex: Option<Entity>,
13321332
fragment: Option<Entity>,
13331333
) -> error::Result<Entity> {
13341334
app_mut(|app| {
13351335
app.world_mut()
1336-
.run_system_cached_with(material::custom::create_from_shaders, (vertex, fragment))
1337-
.unwrap()
1338-
})
1339-
}
1340-
1341-
pub fn material_create_custom(shader_source: &str) -> error::Result<Entity> {
1342-
app_mut(|app| {
1343-
app.world_mut()
1344-
.run_system_cached_with(material::custom::create_custom, shader_source.to_string())
1336+
.run_system_cached_with(material::custom::create_custom, (vertex, fragment))
13451337
.unwrap()
13461338
})
13471339
}

crates/processing_render/src/material/custom.rs

Lines changed: 13 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -40,22 +40,23 @@ use bevy::{
4040

4141
use bevy_naga_reflect::dynamic_shader::DynamicShader;
4242

43+
use bevy::shader::Shader as ShaderAsset;
44+
4345
use crate::error::{ProcessingError, Result};
4446
use crate::material::MaterialValue;
4547
use crate::render::material::UntypedMaterial;
4648

4749
#[derive(Asset, TypePath, Clone)]
4850
pub struct CustomMaterial {
4951
pub shader: DynamicShader,
50-
pub vertex_shader: Option<Handle<Shader>>,
51-
pub fragment_shader: Option<Handle<Shader>>,
52+
pub vertex_shader: Option<Handle<ShaderAsset>>,
53+
pub fragment_shader: Option<Handle<ShaderAsset>>,
5254
}
5355

54-
/// A compiled shader program that can be used to create multiple material instances.
5556
#[derive(Component)]
56-
pub struct ShaderProgram {
57+
pub struct Shader {
5758
pub module: naga::Module,
58-
pub shader_handle: Handle<Shader>,
59+
pub shader_handle: Handle<ShaderAsset>,
5960
}
6061

6162
#[derive(Component, Clone)]
@@ -136,71 +137,30 @@ fn detect_stages(module: &naga::Module) -> (bool, bool) {
136137
(has_vertex, has_fragment)
137138
}
138139

139-
/// Create a custom material from WGSL/WESL shader source (convenience: compile + create in one step).
140-
pub fn create_custom(
141-
In(source): In<String>,
142-
mut commands: Commands,
143-
mut shaders: ResMut<Assets<Shader>>,
144-
mut custom_materials: ResMut<Assets<CustomMaterial>>,
145-
) -> Result<Entity> {
146-
let (compiled_wgsl, module) = compile_shader(&source)?;
147-
let (has_vertex, has_fragment) = detect_stages(&module);
148-
149-
let mut shader = DynamicShader::new(module)
150-
.map_err(|e| ProcessingError::ShaderCompilationError(format!("{e}")))?;
151-
shader.init();
152-
153-
let shader_handle = shaders.add(Shader::from_wgsl(compiled_wgsl, "custom_material"));
154-
155-
let material = CustomMaterial {
156-
shader,
157-
vertex_shader: if has_vertex {
158-
Some(shader_handle.clone())
159-
} else {
160-
None
161-
},
162-
fragment_shader: if has_fragment {
163-
Some(shader_handle)
164-
} else {
165-
None
166-
},
167-
};
168-
let handle = custom_materials.add(material);
169-
let entity = commands.spawn(UntypedMaterial(handle.untyped())).id();
170-
Ok(entity)
171-
}
172-
173-
/// Compile WGSL source and spawn an entity with ShaderProgram.
174140
pub fn create_shader(
175141
In(source): In<String>,
176142
mut commands: Commands,
177-
mut shaders: ResMut<Assets<Shader>>,
143+
mut shaders: ResMut<Assets<ShaderAsset>>,
178144
) -> Result<Entity> {
179145
let (compiled_wgsl, module) = compile_shader(&source)?;
180-
let shader_handle = shaders.add(Shader::from_wgsl(compiled_wgsl, "custom_material"));
146+
let shader_handle = shaders.add(ShaderAsset::from_wgsl(compiled_wgsl, "custom_material"));
181147
Ok(commands
182-
.spawn(ShaderProgram {
148+
.spawn(Shader {
183149
module,
184150
shader_handle,
185151
})
186152
.id())
187153
}
188154

189-
/// Destroy a shader program entity.
190155
pub fn destroy_shader(In(entity): In<Entity>, mut commands: Commands) -> Result<()> {
191156
commands.entity(entity).despawn();
192157
Ok(())
193158
}
194159

195-
/// Create a CustomMaterial from separate vertex and fragment ShaderPrograms.
196-
///
197-
/// At least one of `vertex` or `fragment` must be `Some`. The `DynamicShader`
198-
/// (uniform storage) is built from whichever module contains `@group(4)` bindings
199-
/// (fragment preferred, falls back to vertex).
200-
pub fn create_from_shaders(
160+
pub fn create_custom(
201161
In((vertex_entity, fragment_entity)): In<(Option<Entity>, Option<Entity>)>,
202162
mut commands: Commands,
203-
shader_programs: Query<&ShaderProgram>,
163+
shader_programs: Query<&Shader>,
204164
mut custom_materials: ResMut<Assets<CustomMaterial>>,
205165
) -> Result<Entity> {
206166
let vertex_program = vertex_entity
@@ -212,15 +172,14 @@ pub fn create_from_shaders(
212172
.transpose()
213173
.map_err(|_| ProcessingError::ShaderNotFound)?;
214174

215-
// Build DynamicShader from the module that provides @group(4) bindings.
216-
// Prefer fragment, fall back to vertex.
175+
// Prefer fragment module for reflection, fall back to vertex.
217176
let reflection_module = fragment_program
218177
.map(|p| &p.module)
219178
.or(vertex_program.map(|p| &p.module))
220179
.ok_or(ProcessingError::ShaderNotFound)?;
221180

222181
let mut shader = DynamicShader::new(reflection_module.clone())
223-
.map_err(|e| ProcessingError::ShaderCompilationError(format!("{e}")))?;
182+
.map_err(|e| ProcessingError::ShaderCompilationError(e.to_string()))?;
224183
shader.init();
225184

226185
let material = CustomMaterial {
@@ -232,20 +191,14 @@ pub fn create_from_shaders(
232191
Ok(commands.spawn(UntypedMaterial(handle.untyped())).id())
233192
}
234193

235-
/// Set a property on a custom material by field name.
236-
///
237-
/// Supports top-level parameters (e.g. the uniform var name) and automatic
238-
/// search into struct fields (e.g. "color" found inside a uniform struct).
239194
pub fn set_property(material: &mut CustomMaterial, name: &str, value: &MaterialValue) -> Result<()> {
240195
let reflect_value: Box<dyn PartialReflect> = material_value_to_reflect(value)?;
241196

242-
// Try top-level parameter first
243197
if let Some(field) = material.shader.field_mut(name) {
244198
field.apply(&*reflect_value);
245199
return Ok(());
246200
}
247201

248-
// Search struct parameters for a matching nested field
249202
let param_name = find_param_containing_field(&material.shader, name);
250203
if let Some(param_name) = param_name {
251204
if let Some(param) = material.shader.field_mut(&param_name) {
@@ -281,7 +234,6 @@ fn material_value_to_reflect(value: &MaterialValue) -> Result<Box<dyn PartialRef
281234
})
282235
}
283236

284-
/// Find which top-level parameter (struct) contains a field with the given name.
285237
fn find_param_containing_field(shader: &DynamicShader, field_name: &str) -> Option<String> {
286238
for i in 0..shader.field_len() {
287239
if let Some(field) = shader.field_at(i) {
@@ -295,10 +247,6 @@ fn find_param_containing_field(shader: &DynamicShader, field_name: &str) -> Opti
295247
None
296248
}
297249

298-
// ---------------------------------------------------------------------------
299-
// Plugin
300-
// ---------------------------------------------------------------------------
301-
302250
pub struct CustomMaterialPlugin;
303251

304252
impl Plugin for CustomMaterialPlugin {
@@ -330,16 +278,10 @@ impl Plugin for CustomMaterialPlugin {
330278
}
331279
}
332280

333-
// ---------------------------------------------------------------------------
334-
// Render-world init
335-
// ---------------------------------------------------------------------------
336-
337281
fn init_custom_material_resources(
338282
mut bind_group_allocators: ResMut<MaterialBindGroupAllocators>,
339283
render_device: Res<RenderDevice>,
340284
) {
341-
// Minimal placeholder layout — actual layouts are provided per-allocation
342-
// via allocate_unprepared in non-bindless mode.
343285
let bind_group_layout = BindGroupLayoutDescriptor::new("custom_material_layout", &[]);
344286

345287
bind_group_allocators.insert(
@@ -354,10 +296,6 @@ fn init_custom_material_resources(
354296
);
355297
}
356298

357-
// ---------------------------------------------------------------------------
358-
// ErasedRenderAsset
359-
// ---------------------------------------------------------------------------
360-
361299
impl ErasedRenderAsset for CustomMaterial {
362300
type SourceAsset = CustomMaterial;
363301
type ErasedAsset = PreparedMaterial;
@@ -384,12 +322,10 @@ impl ErasedRenderAsset for CustomMaterial {
384322
) -> std::result::Result<Self::ErasedAsset, PrepareAssetError<Self::SourceAsset>> {
385323
let reflection = source_asset.shader.reflection();
386324

387-
// Build bind group layout from shader reflection (group 3 = material bind group index)
388325
let layout_entries = reflection.bind_group_layout(3);
389326
let bind_group_layout =
390327
BindGroupLayoutDescriptor::new("custom_material_bind_group", &layout_entries);
391328

392-
// Create GPU bindings from the DynamicShader's current parameter values
393329
let bindings = reflection.create_bindings(3, &source_asset.shader, render_device, gpu_images);
394330

395331
let unprepared = UnpreparedBindGroup {
@@ -400,7 +336,6 @@ impl ErasedRenderAsset for CustomMaterial {
400336
.get_mut(&TypeId::of::<CustomMaterial>())
401337
.unwrap();
402338

403-
// Register binding in RenderMaterialBindings so the draw function can find it
404339
let binding = match render_material_bindings.entry(asset_id.into()) {
405340
Entry::Occupied(mut occupied_entry) => {
406341
bind_group_allocator.free(*occupied_entry.get());
@@ -413,7 +348,6 @@ impl ErasedRenderAsset for CustomMaterial {
413348
.insert(bind_group_allocator.allocate_unprepared(unprepared, &bind_group_layout)),
414349
};
415350

416-
// Draw function
417351
let draw_function = opaque_draw_functions
418352
.read()
419353
.id::<DrawMaterial>();
@@ -439,10 +373,6 @@ impl ErasedRenderAsset for CustomMaterial {
439373
}
440374
}
441375

442-
// ---------------------------------------------------------------------------
443-
// Extract systems
444-
// ---------------------------------------------------------------------------
445-
446376
fn extract_custom_materials(
447377
mut material_instances: ResMut<RenderMaterialInstances>,
448378
changed_query: Extract<
@@ -493,10 +423,6 @@ fn extract_custom_materials_that_need_specializations_removed(
493423
}
494424
}
495425

496-
// ---------------------------------------------------------------------------
497-
// Specialization tracking (main world)
498-
// ---------------------------------------------------------------------------
499-
500426
fn check_entities_needing_specialization(
501427
needs_specialization: Query<
502428
Entity,

crates/processing_render/src/render/material.rs

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,9 @@ use std::ops::Deref;
33

44
use crate::material::custom::{CustomMaterial, CustomMaterial3d};
55

6-
/// A component that holds an untyped handle to a material. This allows the main render loop
7-
/// to be agnostic of the specific material types being used, and allows for dynamic material
8-
/// creation based on the `MaterialKey`.
96
#[derive(Component, Deref)]
107
pub struct UntypedMaterial(pub UntypedHandle);
118

12-
/// Defines the current material for a batch, which can be used to determine when to flush the
13-
/// current batch and start a new one.
149
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
1510
pub enum MaterialKey {
1611
Color {
@@ -75,17 +70,11 @@ impl MaterialKey {
7570
};
7671
materials.add(mat).untyped()
7772
}
78-
MaterialKey::Custom(_) => {
79-
unreachable!(
80-
"Custom materials are resolved directly from entity handles, not via to_material"
81-
)
82-
}
73+
MaterialKey::Custom(_) => unreachable!(),
8374
}
8475
}
8576
}
8677

87-
/// A system that adds a `MeshMaterial3d` component to any entity with an `UntypedMaterial` that can
88-
/// be typed as a `StandardMaterial`.
8978
pub fn add_standard_materials(mut commands: Commands, meshes: Query<(Entity, &UntypedMaterial)>) {
9079
for (entity, handle) in meshes.iter() {
9180
let handle = handle.deref().clone();
@@ -95,8 +84,6 @@ pub fn add_standard_materials(mut commands: Commands, meshes: Query<(Entity, &Un
9584
}
9685
}
9786

98-
/// A system that adds a `CustomMaterial3d` component to any entity with an `UntypedMaterial` that
99-
/// can be typed as a `CustomMaterial`.
10087
pub fn add_custom_materials(mut commands: Commands, meshes: Query<(Entity, &UntypedMaterial)>) {
10188
for (entity, handle) in meshes.iter() {
10289
let handle = handle.deref().clone();

0 commit comments

Comments
 (0)