Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 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
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ path = "examples/animated_mesh.rs"
name = "custom_attribute"
path = "examples/custom_attribute.rs"

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

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

#[unsafe(no_mangle)]
pub extern "C" fn processing_light_create_directional(
graphics_id: u64,
color: Color,
illuminance: f32,
) -> u64 {
error::clear_error();
let graphics_entity = Entity::from_bits(graphics_id);
error::check(|| light_create_directional(graphics_entity, color.into(), illuminance))
.map(|e| e.to_bits())
.unwrap_or(0)
}

#[unsafe(no_mangle)]
pub extern "C" fn processing_light_create_point(
graphics_id: u64,
color: Color,
intensity: f32,
range: f32,
radius: f32,
) -> u64 {
error::clear_error();
let graphics_entity = Entity::from_bits(graphics_id);
error::check(|| light_create_point(graphics_entity, color.into(), intensity, range, radius))
.map(|e| e.to_bits())
.unwrap_or(0)
}

#[unsafe(no_mangle)]
pub extern "C" fn processing_light_create_spot(
graphics_id: u64,
color: Color,
intensity: f32,
range: f32,
radius: f32,
inner_angle: f32,
outer_angle: f32,
) -> u64 {
error::clear_error();
let graphics_entity = Entity::from_bits(graphics_id);
error::check(|| {
light_create_spot(
graphics_entity,
color.into(),
intensity,
range,
radius,
inner_angle,
outer_angle,
)
})
.map(|e| e.to_bits())
.unwrap_or(0)
}
63 changes: 62 additions & 1 deletion crates/processing_render/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pub mod error;
pub mod geometry;
mod graphics;
pub mod image;
pub mod light;
pub mod render;
mod surface;
pub mod transform;
Expand All @@ -25,7 +26,7 @@ use tracing::debug;
use crate::geometry::{AttributeFormat, AttributeValue};
use crate::graphics::flush;
use crate::{
graphics::GraphicsPlugin, image::ImagePlugin, render::command::DrawCommand,
graphics::GraphicsPlugin, image::ImagePlugin, light::LightPlugin, render::command::DrawCommand,
surface::SurfacePlugin,
};

Expand Down Expand Up @@ -248,6 +249,7 @@ fn create_app(config: Config) -> App {
GraphicsPlugin,
SurfacePlugin,
geometry::GeometryPlugin,
LightPlugin,
));
app.add_systems(First, (clear_transient_meshes, activate_cameras))
.add_systems(Update, flush_draw_commands.before(AssetEventSystems));
Expand Down Expand Up @@ -774,6 +776,65 @@ pub fn image_destroy(entity: Entity) -> error::Result<()> {
})
}

pub fn light_create_directional(
graphics_entity: Entity,
color: Color,
illuminance: f32,
) -> error::Result<Entity> {
app_mut(|app| {
app.world_mut()
.run_system_cached_with(
light::create_directional,
(graphics_entity, color, illuminance),
)
.unwrap()
})
}

pub fn light_create_point(
graphics_entity: Entity,
color: Color,
intensity: f32,
range: f32,
radius: f32,
) -> error::Result<Entity> {
app_mut(|app| {
app.world_mut()
.run_system_cached_with(
light::create_point,
(graphics_entity, color, intensity, range, radius),
)
.unwrap()
})
}

pub fn light_create_spot(
graphics_entity: Entity,
color: Color,
intensity: f32,
range: f32,
radius: f32,
inner_angle: f32,
outer_angle: f32,
) -> error::Result<Entity> {
app_mut(|app| {
app.world_mut()
.run_system_cached_with(
light::create_spot,
(
graphics_entity,
color,
intensity,
range,
radius,
inner_angle,
outer_angle,
),
)
.unwrap()
})
}

pub fn geometry_layout_create() -> error::Result<Entity> {
app_mut(|app| {
Ok(app
Expand Down
86 changes: 86 additions & 0 deletions crates/processing_render/src/light.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
//! A light in Processing
//!

use bevy::{camera::visibility::RenderLayers, prelude::*};

use crate::{error::ProcessingError, graphics::Graphics};

pub struct LightPlugin;

impl Plugin for LightPlugin {
fn build(&self, _app: &mut App) {}
}

pub fn create_directional(
In((entity, color, illuminance)): In<(Entity, Color, f32)>,
mut commands: Commands,
graphics: Query<&RenderLayers, With<Graphics>>,
) -> Result<Entity, ProcessingError> {
let layer = graphics
.get(entity)
.map_err(|_| ProcessingError::GraphicsNotFound)?;
Ok(commands
.spawn((
DirectionalLight {
illuminance,
color,
..default()
},
layer.clone(),
))
.id())
}

pub fn create_point(
In((entity, color, intensity, range, radius)): In<(Entity, Color, f32, f32, f32)>,
mut commands: Commands,
graphics: Query<&RenderLayers, With<Graphics>>,
) -> Result<Entity, ProcessingError> {
let layer = graphics
.get(entity)
.map_err(|_| ProcessingError::GraphicsNotFound)?;
Ok(commands
.spawn((
PointLight {
intensity,
color,
range,
radius,
..default()
},
layer.clone(),
))
.id())
}

pub fn create_spot(
In((entity, color, intensity, range, radius, inner_angle, outer_angle)): In<(
Entity,
Color,
f32,
f32,
f32,
f32,
f32,
)>,
mut commands: Commands,
graphics: Query<&RenderLayers, With<Graphics>>,
) -> Result<Entity, ProcessingError> {
let layer = graphics
.get(entity)
.map_err(|_| ProcessingError::GraphicsNotFound)?;
Ok(commands
.spawn((
SpotLight {
color,
intensity,
range,
radius,
inner_angle,
outer_angle,
..default()
},
layer.clone(),
))
.id())
}
2 changes: 1 addition & 1 deletion crates/processing_render/src/render/material.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ impl MaterialKey {
pub fn to_material(&self) -> StandardMaterial {
StandardMaterial {
base_color: Color::WHITE,
unlit: true,
unlit: false,
cull_mode: None,
base_color_texture: self.background_image.clone(),
alpha_mode: if self.transparent {
Expand Down
6 changes: 5 additions & 1 deletion docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ rendering texture that the camera draws to (`ViewTarget`), which is not typicall
For consistency, all image functions should accept a graphics object, although its internal image representation is
not guaranteed to be the same as a user-created image.

### Light

[//]: # (TODO: Document Image API object)

### Image

Images are 2D or 3D arrays of pixels that can be drawn onto surfaces. They can be created from files, generated procedurally,
Expand Down Expand Up @@ -85,4 +89,4 @@ can also be used to implement 2D image processing effects, etc.

### Shader

[//]: # (TODO: Document Shader API object, do we even need this with a sufficiently robust Material API?)
[//]: # (TODO: Document Shader API object, do we even need this with a sufficiently robust Material API?)
98 changes: 98 additions & 0 deletions examples/lights.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
mod glfw;

use glfw::GlfwContext;
use processing::prelude::*;
use processing_render::render::command::DrawCommand;

fn main() {
match sketch() {
Ok(_) => {
eprintln!("Sketch completed successfully");
exit(0).unwrap();
}
Err(e) => {
eprintln!("Sketch error: {:?}", e);
exit(1).unwrap();
}
};
}

fn sketch() -> error::Result<()> {
let mut glfw_ctx = GlfwContext::new(400, 400)?;
init(Config::default())?;

let width = 400;
let height = 400;
let scale_factor = 1.0;

let surface = glfw_ctx.create_surface(width, height, scale_factor)?;
let graphics = graphics_create(surface, width, height)?;
let box_geo = geometry_box(100.0, 100.0, 100.0)?;

// We will only declare lights in `setup`
// rather than calling some sort of `light()` method inside of `draw`

// create a directional light
let _dir_light =
light_create_directional(graphics, bevy::color::Color::srgb(0.35, 0.25, 0.5), 500.0)?;

// create a point light
let point_light_a = light_create_point(
graphics,
bevy::color::Color::srgb(1.0, 0.5, 0.25),
1_000_000.0,
200.0,
0.5,
)?;
transform_set_position(point_light_a, -25.0, 5.0, 51.0)?;
transform_look_at(point_light_a, 0.0, 0.0, 0.0)?;

// create another point light
let point_light_b = light_create_point(
graphics,
bevy::color::Color::srgb(0.0, 0.5, 0.75),
2_000_000.0,
200.0,
0.25,
)?;
transform_set_position(point_light_b, 0.0, 5.0, 50.5)?;
transform_look_at(point_light_b, 0.0, 0.0, 0.0)?;

// and a spot light, too!
let spot_light = light_create_spot(
graphics,
bevy::color::Color::srgb(0.25, 0.8, 0.19),
15.0 * 1_000_000.0,
200.0,
0.84,
0.0,
core::f32::consts::FRAC_PI_4,
)?;
transform_set_position(spot_light, 40.0, 0.0, 70.0)?;
transform_look_at(spot_light, 0.0, 0.0, 0.0)?;

graphics_mode_3d(graphics)?;
transform_set_position(graphics, 100.0, 100.0, 300.0)?;
transform_look_at(graphics, 0.0, 0.0, 0.0)?;

let mut angle = 0.0;

while glfw_ctx.poll_events() {
graphics_begin_draw(graphics)?;

graphics_record_command(
graphics,
DrawCommand::BackgroundColor(bevy::color::Color::srgb(0.18, 0.20, 0.15)),
)?;

graphics_record_command(graphics, DrawCommand::PushMatrix)?;
graphics_record_command(graphics, DrawCommand::Rotate { angle })?;
graphics_record_command(graphics, DrawCommand::Geometry(box_geo))?;
graphics_record_command(graphics, DrawCommand::PopMatrix)?;

graphics_end_draw(graphics)?;

angle += 0.02;
}
Ok(())
}