Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion crates/processing_render/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ use tracing::debug;

use crate::geometry::{AttributeFormat, AttributeValue};
use crate::graphics::flush;
use crate::render::material::add_standard_materials;
use crate::{
graphics::GraphicsPlugin, image::ImagePlugin, light::LightPlugin, render::command::DrawCommand,
surface::SurfacePlugin,
Expand Down Expand Up @@ -252,7 +253,13 @@ fn create_app(config: Config) -> App {
LightPlugin,
));
app.add_systems(First, (clear_transient_meshes, activate_cameras))
.add_systems(Update, flush_draw_commands.before(AssetEventSystems));
.add_systems(
Update,
(
flush_draw_commands.before(AssetEventSystems),
add_standard_materials.after(flush_draw_commands),
),
);

app
}
Expand Down
74 changes: 59 additions & 15 deletions crates/processing_render/src/render/material.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,68 @@
use bevy::{prelude::*, render::alpha::AlphaMode};
use std::ops::Deref;

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

/// Defines the current material for a batch, which can be used to determine when to flush the
/// current batch and start a new one.
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub struct MaterialKey {
pub transparent: bool,
pub background_image: Option<Handle<Image>>,
pub enum MaterialKey {
Color {
transparent: bool,
background_image: Option<Handle<Image>>,
},
Pbr {},
Custom(Entity),
}

impl MaterialKey {
pub fn to_material(&self) -> StandardMaterial {
StandardMaterial {
base_color: Color::WHITE,
unlit: true,
cull_mode: None,
base_color_texture: self.background_image.clone(),
alpha_mode: if self.transparent {
AlphaMode::Blend
} else {
AlphaMode::Opaque
},
..default()
pub fn to_material(
&self,
standard_materials: &mut ResMut<Assets<StandardMaterial>>,
) -> UntypedHandle {
match self {
MaterialKey::Color {
background_image,
transparent,
} => {
let mat = StandardMaterial {
base_color: Color::WHITE,
unlit: true,
cull_mode: None,
base_color_texture: background_image.clone(),
alpha_mode: if *transparent {
AlphaMode::Blend
} else {
AlphaMode::Opaque
},
..default()
};
standard_materials.add(mat).untyped()
}
MaterialKey::Pbr { .. } => {
todo!("implement pbr materials")
}
MaterialKey::Custom(_) => {
todo!("implement custom materials")
}
}
}
}

/// A system that adds a `MeshMaterial3d` component to any entity with an `UntypedMaterial` that can
/// be typed as a `StandardMaterial`.
pub(crate) fn add_standard_materials(
mut commands: Commands,
meshes: Query<(Entity, &UntypedMaterial)>,
) {
for (entity, handle) in meshes.iter() {
let handle = handle.deref().clone();
if let Ok(handle) = handle.try_typed::<StandardMaterial>() {
commands.entity(entity).insert(MeshMaterial3d(handle));
Comment on lines +58 to +65
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When we want to support MeshMaterial2d, how would this look? For now we don't need to worry because we're focused on 3D

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right now we just implement 2d via 3d, but this would allow us to switch to that later if we wanted, or vector graphics, or whatever.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

amazing, thanks!

}
}
}
27 changes: 14 additions & 13 deletions crates/processing_render/src/render/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use material::MaterialKey;
use primitive::{TessellationMode, empty_mesh};
use transform::TransformStack;

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

#[derive(Component)]
Expand Down Expand Up @@ -153,15 +154,15 @@ pub fn flush_draw_commands(
let mesh = create_ndc_background_quad(world_from_clip, color, false);
let mesh_handle = res.meshes.add(mesh);

let material_key = MaterialKey {
let material_key = MaterialKey::Color {
transparent: color.alpha() < 1.0,
background_image: None,
};
let material_handle = res.materials.add(material_key.to_material());
let material_handle = material_key.to_material(&mut res.materials);

res.commands.spawn((
Mesh3d(mesh_handle),
MeshMaterial3d(material_handle),
UntypedMaterial(material_handle),
BelongsToGraphics(batch.graphics_entity),
Transform::IDENTITY,
batch.render_layers.clone(),
Expand All @@ -180,15 +181,15 @@ pub fn flush_draw_commands(
let mesh = create_ndc_background_quad(world_from_clip, Color::WHITE, true);
let mesh_handle = res.meshes.add(mesh);

let material_key = MaterialKey {
let material_key = MaterialKey::Color {
transparent: false,
background_image: Some(p_image.handle.clone()),
};
let material_handle = res.materials.add(material_key.to_material());
let material_handle = material_key.to_material(&mut res.materials);

res.commands.spawn((
Mesh3d(mesh_handle),
MeshMaterial3d(material_handle),
UntypedMaterial(material_handle),
BelongsToGraphics(batch.graphics_entity),
Transform::IDENTITY,
batch.render_layers.clone(),
Expand All @@ -214,20 +215,20 @@ pub fn flush_draw_commands(

// TODO: Implement state based material API
// https://github.com/processing/libprocessing/issues/10
let material_key = MaterialKey {
let material_key = MaterialKey::Color {
transparent: false, // TODO: detect from geometry colors
background_image: None,
};

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

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

res.commands.spawn((
Mesh3d(geometry.handle.clone()),
MeshMaterial3d(material_handle),
UntypedMaterial(material_handle),
BelongsToGraphics(batch.graphics_entity),
transform,
batch.render_layers.clone(),
Expand Down Expand Up @@ -265,7 +266,7 @@ fn spawn_mesh(res: &mut RenderResources, batch: &mut BatchState, mesh: Mesh, z_o
};

let mesh_handle = res.meshes.add(mesh);
let material_handle = res.materials.add(material_key.to_material());
let material_handle = material_key.to_material(&mut res.materials);

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

res.commands.spawn((
Mesh3d(mesh_handle),
MeshMaterial3d(material_handle),
UntypedMaterial(material_handle),
BelongsToGraphics(batch.graphics_entity),
transform,
batch.render_layers.clone(),
Expand Down Expand Up @@ -311,7 +312,7 @@ fn add_fill(
let Some(color) = state.fill_color else {
return;
};
let material_key = MaterialKey {
let material_key = MaterialKey::Color {
transparent: state.fill_is_transparent(),
background_image: None,
};
Expand All @@ -335,7 +336,7 @@ fn add_stroke(
return;
};
let stroke_weight = state.stroke_weight;
let material_key = MaterialKey {
let material_key = MaterialKey::Color {
transparent: state.stroke_is_transparent(),
background_image: None,
};
Expand Down
1 change: 1 addition & 0 deletions crates/processing_render/src/surface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
//! - WebAssembly: `create_surface_web`
#[cfg(any(target_os = "linux", target_arch = "wasm32"))]
use std::ffi::c_void;
#[cfg(not(target_os = "windows"))]
use std::ptr::NonNull;

use bevy::{
Expand Down