Material render settings by tychedelia · Pull Request #223 · processing/libprocessing · GitHub
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
55 changes: 43 additions & 12 deletions crates/processing_ffi/src/lib.rs
51 changes: 31 additions & 20 deletions crates/processing_pyo3/src/material.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,20 +60,18 @@ fn apply_albedo(entity: Entity, value: &Bound<'_, PyAny>) -> PyResult<()> {
return material_set_albedo_buffer(entity, buf.entity)
.map_err(|e| PyRuntimeError::new_err(format!("{e}")));
}
if let Ok(c) = value.extract::<PyRef<PyColor>>() {
let rgba = if let Ok(c) = value.extract::<PyRef<PyColor>>() {
let srgba: bevy::color::Srgba = c.0.into();
return material_set_albedo_color(
entity,
[srgba.red, srgba.green, srgba.blue, srgba.alpha],
)
.map_err(|e| PyRuntimeError::new_err(format!("{e}")));
}
if let Ok(rgba) = value.extract::<[f32; 4]>() {
return material_set_albedo_color(entity, rgba)
.map_err(|e| PyRuntimeError::new_err(format!("{e}")));
}
if let Ok(rgb) = value.extract::<[f32; 3]>() {
return material_set_albedo_color(entity, [rgb[0], rgb[1], rgb[2], 1.0])
Some([srgba.red, srgba.green, srgba.blue, srgba.alpha])
} else if let Ok(rgba) = value.extract::<[f32; 4]>() {
Some(rgba)
} else if let Ok(rgb) = value.extract::<[f32; 3]>() {
Some([rgb[0], rgb[1], rgb[2], 1.0])
} else {
None
};
if let Some(rgba) = rgba {
return material_set(entity, "color", shader_value::ShaderValue::Float4(rgba))
.map_err(|e| PyRuntimeError::new_err(format!("{e}")));
}
Err(PyRuntimeError::new_err(format!(
Expand All @@ -82,15 +80,29 @@ fn apply_albedo(entity: Entity, value: &Bound<'_, PyAny>) -> PyResult<()> {
)))
}

fn py_truthy(value: &Bound<'_, PyAny>) -> PyResult<bool> {
value
.extract::<bool>()
.or_else(|_| value.extract::<f64>().map(|f| f > 0.5))
}

fn apply_kwargs(entity: Entity, kwargs: &Bound<'_, PyDict>) -> PyResult<()> {
for (key, value) in kwargs.iter() {
let name: String = key.extract()?;
if name == "albedo" {
apply_albedo(entity, &value)?;
continue;
let rt = |e| PyRuntimeError::new_err(format!("{e}"));
match name.as_str() {
"albedo" => apply_albedo(entity, &value)?,
"unlit" => material_set_unlit(entity, py_truthy(&value)?).map_err(rt)?,
"double_sided" => material_set_double_sided(entity, py_truthy(&value)?).map_err(rt)?,
"depth_write" => material_set_depth_write(entity, py_truthy(&value)?).map_err(rt)?,
"alpha_mode" => {
material_set_alpha_mode(entity, value.extract::<u8>()?, 0.5).map_err(rt)?
}
_ => {
let v = py_to_shader_value(&value)?;
material_set(entity, &name, v).map_err(rt)?;
}
}
let v = py_to_shader_value(&value)?;
material_set(entity, &name, v).map_err(|e| PyRuntimeError::new_err(format!("{e}")))?;
}
Ok(())
}
Expand Down Expand Up @@ -127,8 +139,7 @@ impl Material {
#[pyo3(signature = (**kwargs))]
pub fn unlit(kwargs: Option<&Bound<'_, PyDict>>) -> PyResult<Self> {
let entity = material_create_pbr().map_err(|e| PyRuntimeError::new_err(format!("{e}")))?;
material_set(entity, "unlit", shader_value::ShaderValue::Float(1.0))
.map_err(|e| PyRuntimeError::new_err(format!("{e}")))?;
material_set_unlit(entity, true).map_err(|e| PyRuntimeError::new_err(format!("{e}")))?;
if let Some(kwargs) = kwargs {
apply_kwargs(entity, kwargs)?;
}
Expand Down
5 changes: 4 additions & 1 deletion crates/processing_render/src/gltf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,10 @@ pub fn material(
.resource_mut::<Assets<ProcessingExtendedMaterial>>()
.add(ExtendedMaterial {
base: standard,
extension: ProcessingMaterial { blend_state: None },
extension: ProcessingMaterial {
blend_state: None,
depth_write: None,
},
});
let entity = world.spawn(UntypedMaterial(handle.untyped())).id();
Ok(entity)
Expand Down
100 changes: 47 additions & 53 deletions crates/processing_render/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1721,65 +1721,16 @@ pub fn material_create_pbr() -> error::Result<Entity> {
/// `material_create_pbr` with `unlit = true` set on the base StandardMaterial.
pub fn material_create_unlit() -> error::Result<Entity> {
let entity = material_create_pbr()?;
material_set(entity, "unlit", shader_value::ShaderValue::Float(1.0))?;
material_set_unlit(entity, true)?;
Ok(entity)
}

/// set the albedo source to a constant srgba color. If the material is
/// currently buffer-backed, swaps the asset back to plain PBR while
/// preserving every other `StandardMaterial` field.
pub fn material_set_albedo_color(entity: Entity, color: [f32; 4]) -> error::Result<()> {
use crate::material::ProcessingMaterial;
use crate::particles::material::ParticlesMaterial;
use crate::render::material::UntypedMaterial;
use bevy::pbr::ExtendedMaterial;

type DefaultMat = ExtendedMaterial<StandardMaterial, ProcessingMaterial>;

app_mut(|app| {
let untyped = app
.world()
.get::<UntypedMaterial>(entity)
.ok_or(error::ProcessingError::MaterialNotFound)?
.0
.clone();
let new_color = Color::srgba(color[0], color[1], color[2], color[3]);

if let Ok(handle) = untyped.clone().try_typed::<DefaultMat>() {
let mut mats = app.world_mut().resource_mut::<Assets<DefaultMat>>();
let mat = mats
.get_mut(&handle)
.ok_or(error::ProcessingError::MaterialNotFound)?;
mat.into_inner().base.base_color = new_color;
return Ok(());
}

let Ok(handle) = untyped.try_typed::<ParticlesMaterial>() else {
return Err(error::ProcessingError::MaterialNotFound);
};
let world = app.world_mut();
let preserved = {
let mut mats = world.resource_mut::<Assets<ParticlesMaterial>>();
let mat = mats
.get(&handle)
.ok_or(error::ProcessingError::MaterialNotFound)?;
let mut base = mat.base.clone();
base.base_color = new_color;
mats.remove(&handle);
base
};
let new_handle = world
.resource_mut::<Assets<DefaultMat>>()
.add(ExtendedMaterial {
base: preserved,
extension: ProcessingMaterial { blend_state: None },
});
world
.entity_mut(entity)
.insert(UntypedMaterial(new_handle.untyped()));
Ok(())
})
}
// NOTE: constant albedo/emissive are plain PBR uniforms — set them via
// `material_set(entity, "color" | "emissive", Float4(..))`. Only the
// per-particle *buffer* variants are special (see material_set_*_buffer below).

#[derive(Copy, Clone)]
enum ParticlesBufferSlot {
Expand Down Expand Up @@ -1893,6 +1844,49 @@ pub fn material_set(
})
}

pub fn material_set_alpha_mode(entity: Entity, mode: u8, cutoff: f32) -> error::Result<()> {
app_mut(|app| {
app.world_mut()
.run_system_cached_with(material::set_alpha_mode, (entity, mode, cutoff))
.unwrap()
})
}

pub fn material_set_double_sided(entity: Entity, value: bool) -> error::Result<()> {
app_mut(|app| {
app.world_mut()
.run_system_cached_with(material::set_double_sided, (entity, value))
.unwrap()
})
}

pub fn material_set_unlit(entity: Entity, value: bool) -> error::Result<()> {
app_mut(|app| {
app.world_mut()
.run_system_cached_with(material::set_unlit, (entity, value))
.unwrap()
})
}

pub fn material_set_depth_write(entity: Entity, value: bool) -> error::Result<()> {
app_mut(|app| {
app.world_mut()
.run_system_cached_with(material::set_depth_write, (entity, value))
.unwrap()
})
}

pub fn material_set_custom_blend(
entity: Entity,
blend: bevy::render::render_resource::BlendState,
) -> error::Result<()> {
app_mut(|app| {
app.world_mut()
.run_system_cached_with(material::set_custom_blend, (entity, blend))
.unwrap()
})
}

pub fn material_destroy(entity: Entity) -> error::Result<()> {
app_mut(|app| {
app.world_mut()
Expand Down
31 changes: 22 additions & 9 deletions crates/processing_render/src/material/custom.rs
Loading
Loading