Skip to content
Open
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
8 changes: 8 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,14 @@ path = "examples/custom_attribute.rs"
name = "lights"
path = "examples/lights.rs"

[[example]]
name = "materials"
path = "examples/materials.rs"

[[example]]
name = "pbr"
path = "examples/pbr.rs"

[profile.wasm-release]
inherits = "release"
opt-level = "z"
Expand Down
67 changes: 67 additions & 0 deletions crates/processing_ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1092,6 +1092,14 @@ pub extern "C" fn processing_geometry_box(width: f32, height: f32, depth: f32) -
.unwrap_or(0)
}

#[unsafe(no_mangle)]
pub extern "C" fn processing_geometry_sphere(radius: f32, sectors: u32, stacks: u32) -> u64 {
error::clear_error();
error::check(|| geometry_sphere(radius, sectors, stacks))
.map(|e| e.to_bits())
.unwrap_or(0)
}

#[unsafe(no_mangle)]
pub extern "C" fn processing_light_create_directional(
graphics_id: u64,
Expand Down Expand Up @@ -1146,3 +1154,62 @@ pub extern "C" fn processing_light_create_spot(
.map(|e| e.to_bits())
.unwrap_or(0)
}

#[unsafe(no_mangle)]
pub extern "C" fn processing_material_create_pbr() -> u64 {
error::clear_error();
error::check(|| material_create_pbr())
.map(|e| e.to_bits())
.unwrap_or(0)
}

#[unsafe(no_mangle)]
pub extern "C" fn processing_material_set_float(
mat_id: u64,
name: *const std::ffi::c_char,
value: f32,
) {
error::clear_error();
let name = unsafe { std::ffi::CStr::from_ptr(name) }.to_str().unwrap();
error::check(|| {
material_set(
Entity::from_bits(mat_id),
name,
material::MaterialValue::Float(value),
)
});
}

#[unsafe(no_mangle)]
pub extern "C" fn processing_material_set_float4(
mat_id: u64,
name: *const std::ffi::c_char,
r: f32,
g: f32,
b: f32,
a: f32,
) {
error::clear_error();
let name = unsafe { std::ffi::CStr::from_ptr(name) }.to_str().unwrap();
error::check(|| {
material_set(
Entity::from_bits(mat_id),
name,
material::MaterialValue::Float4([r, g, b, a]),
)
});
}

#[unsafe(no_mangle)]
pub extern "C" fn processing_material_destroy(mat_id: u64) {
error::clear_error();
error::check(|| material_destroy(Entity::from_bits(mat_id)));
}

#[unsafe(no_mangle)]
pub extern "C" fn processing_material(window_id: u64, mat_id: u64) {
error::clear_error();
let window_entity = Entity::from_bits(window_id);
let mat_entity = Entity::from_bits(mat_id);
error::check(|| graphics_record_command(window_entity, DrawCommand::Material(mat_entity)));
}
27 changes: 27 additions & 0 deletions crates/processing_pyo3/examples/materials.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from processing import *

mat = None

def setup():
global mat
size(800, 600)
mode_3d()

dir_light = create_directional_light(1.0, 0.98, 0.95, 1500.0)
point_light = create_point_light(1.0, 1.0, 1.0, 100000.0, 800.0, 0.0)
point_light.position(200.0, 200.0, 400.0)

mat = Material()
mat.set_float("roughness", 0.3)
mat.set_float("metallic", 0.8)
mat.set_float4("base_color", 1.0, 0.85, 0.57, 1.0)

def draw():
camera_position(0.0, 0.0, 200.0)
camera_look_at(0.0, 0.0, 0.0)
background(12, 12, 18)

use_material(mat)
draw_sphere(50.0)

run()
17 changes: 17 additions & 0 deletions crates/processing_pyo3/src/graphics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -293,11 +293,23 @@ impl Graphics {
.map_err(|e| PyRuntimeError::new_err(format!("{e}")))
}

pub fn draw_sphere(&self, radius: f32, sectors: u32, stacks: u32) -> PyResult<()> {
let sphere_geo = geometry_sphere(radius, sectors, stacks)
.map_err(|e| PyRuntimeError::new_err(format!("{e}")))?;
graphics_record_command(self.entity, DrawCommand::Geometry(sphere_geo))
.map_err(|e| PyRuntimeError::new_err(format!("{e}")))
}

pub fn draw_geometry(&self, geometry: &Geometry) -> PyResult<()> {
graphics_record_command(self.entity, DrawCommand::Geometry(geometry.entity))
.map_err(|e| PyRuntimeError::new_err(format!("{e}")))
}

pub fn use_material(&self, material: &crate::material::Material) -> PyResult<()> {
graphics_record_command(self.entity, DrawCommand::Material(material.entity))
.map_err(|e| PyRuntimeError::new_err(format!("{e}")))
}

pub fn scale(&self, x: f32, y: f32) -> PyResult<()> {
graphics_record_command(self.entity, DrawCommand::Scale { x, y })
.map_err(|e| PyRuntimeError::new_err(format!("{e}")))
Expand All @@ -313,6 +325,11 @@ impl Graphics {
.map_err(|e| PyRuntimeError::new_err(format!("{e}")))
}

pub fn set_material(&self, material: &crate::material::Material) -> PyResult<()> {
graphics_record_command(self.entity, DrawCommand::Material(material.entity))
.map_err(|e| PyRuntimeError::new_err(format!("{e}")))
}

pub fn begin_draw(&self) -> PyResult<()> {
graphics_begin_draw(self.entity).map_err(|e| PyRuntimeError::new_err(format!("{e}")))
}
Expand Down
22 changes: 22 additions & 0 deletions crates/processing_pyo3/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@
//! functions that forward to a singleton Graphics object pub(crate) behind the scenes.
mod glfw;
mod graphics;
pub(crate) mod material;

use graphics::{Geometry, Graphics, Image, Light, Topology, get_graphics, get_graphics_mut};
use material::Material;
use pyo3::{
exceptions::PyRuntimeError,
prelude::*,
Expand All @@ -27,6 +29,7 @@ fn processing(m: &Bound<'_, PyModule>) -> PyResult<()> {
m.add_class::<Image>()?;
m.add_class::<Light>()?;
m.add_class::<Topology>()?;
m.add_class::<Material>()?;
m.add_function(wrap_pyfunction!(size, m)?)?;
m.add_function(wrap_pyfunction!(run, m)?)?;
m.add_function(wrap_pyfunction!(mode_3d, m)?)?;
Expand All @@ -48,6 +51,8 @@ fn processing(m: &Bound<'_, PyModule>) -> PyResult<()> {
m.add_function(wrap_pyfunction!(create_directional_light, m)?)?;
m.add_function(wrap_pyfunction!(create_point_light, m)?)?;
m.add_function(wrap_pyfunction!(create_spot_light, m)?)?;
m.add_function(wrap_pyfunction!(draw_sphere, m)?)?;
m.add_function(wrap_pyfunction!(use_material, m)?)?;

Ok(())
}
Expand Down Expand Up @@ -320,3 +325,20 @@ fn create_spot_light(
) -> PyResult<Light> {
get_graphics(module)?.light_spot(r, g, b, intensity, range, radius, inner_angle, outer_angle)
}

#[pyfunction]
#[pyo3(pass_module, signature = (radius, sectors=32, stacks=18))]
fn draw_sphere(
module: &Bound<'_, PyModule>,
radius: f32,
sectors: u32,
stacks: u32,
) -> PyResult<()> {
get_graphics(module)?.draw_sphere(radius, sectors, stacks)
}

#[pyfunction]
#[pyo3(pass_module, signature = (material))]
fn use_material(module: &Bound<'_, PyModule>, material: &Bound<'_, Material>) -> PyResult<()> {
get_graphics(module)?.use_material(&*material.extract::<PyRef<Material>>()?)
}
37 changes: 37 additions & 0 deletions crates/processing_pyo3/src/material.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use bevy::prelude::Entity;
use processing::prelude::*;
use pyo3::{exceptions::PyRuntimeError, prelude::*};

#[pyclass(unsendable)]
pub struct Material {
pub(crate) entity: Entity,
}

#[pymethods]
impl Material {
#[new]
pub fn new() -> PyResult<Self> {
let entity = material_create_pbr().map_err(|e| PyRuntimeError::new_err(format!("{e}")))?;
Ok(Self { entity })
}

pub fn set_float(&self, name: &str, value: f32) -> PyResult<()> {
material_set(self.entity, name, material::MaterialValue::Float(value))
.map_err(|e| PyRuntimeError::new_err(format!("{e}")))
}

pub fn set_float4(&self, name: &str, r: f32, g: f32, b: f32, a: f32) -> PyResult<()> {
material_set(
self.entity,
name,
material::MaterialValue::Float4([r, g, b, a]),
)
.map_err(|e| PyRuntimeError::new_err(format!("{e}")))
}
}

impl Drop for Material {
fn drop(&mut self) {
let _ = material_destroy(self.entity);
}
}
4 changes: 4 additions & 0 deletions crates/processing_render/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,8 @@ pub enum ProcessingError {
LayoutNotFound,
#[error("Transform not found")]
TransformNotFound,
#[error("Material not found")]
MaterialNotFound,
#[error("Unknown material property: {0}")]
UnknownMaterialProperty(String),
}
22 changes: 22 additions & 0 deletions crates/processing_render/src/geometry/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,28 @@ pub fn create_box(
commands.spawn(Geometry::new(handle, layout_entity)).id()
}

pub fn create_sphere(
In((radius, sectors, stacks)): In<(f32, u32, u32)>,
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
builtins: Res<BuiltinAttributes>,
) -> Entity {
let sphere = Sphere::new(radius);
let mesh = sphere.mesh().uv(sectors, stacks);
let handle = meshes.add(mesh);

let layout_entity = commands
.spawn(VertexLayout::with_attributes(vec![
builtins.position,
builtins.normal,
builtins.color,
builtins.uv,
]))
.id();

commands.spawn(Geometry::new(handle, layout_entity)).id()
}

pub fn normal(world: &mut World, entity: Entity, nx: f32, ny: f32, nz: f32) -> Result<()> {
let mut geometry = world
.get_mut::<Geometry>(entity)
Expand Down
12 changes: 9 additions & 3 deletions crates/processing_render/src/graphics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ use crate::{
Flush,
error::{ProcessingError, Result},
image::{Image, bytes_to_pixels, create_readback_buffer, pixel_size, pixels_to_bytes},
material::DefaultMaterial,
render::{
RenderState,
command::{CommandBuffer, DrawCommand},
Expand Down Expand Up @@ -186,6 +187,7 @@ pub fn create(
mut layer_manager: ResMut<RenderLayersManager>,
p_images: Query<&Image, With<Surface>>,
render_device: Res<RenderDevice>,
default_material: Res<DefaultMaterial>,
) -> Result<Entity> {
// find the surface entity, if it is an image, we will render to that image
// otherwise we will render to the window
Expand Down Expand Up @@ -243,7 +245,7 @@ pub fn create(
Transform::from_xyz(0.0, 0.0, 999.9),
render_layer,
CommandBuffer::new(),
RenderState::default(),
RenderState::new(default_material.0),
SurfaceSize(width, height),
Graphics {
readback_buffer,
Expand Down Expand Up @@ -424,11 +426,15 @@ pub fn destroy(
Ok(())
}

pub fn begin_draw(In(entity): In<Entity>, mut state_query: Query<&mut RenderState>) -> Result<()> {
pub fn begin_draw(
In(entity): In<Entity>,
mut state_query: Query<&mut RenderState>,
default_material: Res<DefaultMaterial>,
) -> Result<()> {
let mut state = state_query
.get_mut(entity)
.map_err(|_| ProcessingError::GraphicsNotFound)?;
state.reset();
state.reset(default_material.0);
Ok(())
}

Expand Down
Loading
Loading