Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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