diff --git a/Cargo.lock b/Cargo.lock index bbe878a..68e2749 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -319,7 +319,7 @@ dependencies = [ [[package]] name = "blue_engine" -version = "0.5.13" +version = "0.5.14" dependencies = [ "android_logger", "bytemuck", diff --git a/Cargo.toml b/Cargo.toml index 749bf80..03391c6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "blue_engine" -version = "0.5.13" +version = "0.5.14" authors = ["Elham Aryanpur "] edition = "2021" description = "General-Purpose, Easy-to-use, Fast, and Portable graphics engine" diff --git a/examples/shapes/square.rs b/examples/shapes/square.rs index a0d9189..2f1d9f3 100644 --- a/examples/shapes/square.rs +++ b/examples/shapes/square.rs @@ -38,7 +38,7 @@ pub fn square(name: impl StringBuffer, engine: &mut Engine) -> eyre::Result<()> ], vec![2, 1, 0, 2, 0, 3], ObjectSettings { - camera_effect: false, + camera_effect: None, ..Default::default() }, &mut engine.renderer, diff --git a/examples/utils/render_order.rs b/examples/utils/render_order.rs index 7c63ccb..5a89bdd 100644 --- a/examples/utils/render_order.rs +++ b/examples/utils/render_order.rs @@ -36,7 +36,7 @@ fn main() { .expect("failed to gete object"); // set a color to differentiate it layer1 - .set_uniform_color(1f32, 0.5, 0f32, 1f32) + .set_color(1f32, 0.5, 0f32, 1f32) .expect("failed to set color"); // move it to left a bit layer1.set_position(-0.5, 0f32, 0f32); @@ -50,7 +50,7 @@ fn main() { .expect("failed to gete object"); // set a color to differentiate it layer2 - .set_uniform_color(0f32, 0f32, 1f32, 1f32) + .set_color(0f32, 0f32, 1f32, 1f32) .expect("failed to set color"); // move it to right a bit layer2.set_position(0.5, 0f32, 0f32); diff --git a/src/header.rs b/src/header.rs index bde4131..938104f 100644 --- a/src/header.rs +++ b/src/header.rs @@ -93,7 +93,7 @@ unsafe impl Sync for Vertex {} /// customize almost everything there is about them! pub struct Object { /// Give your object a name, which can help later on for debugging. - pub name: String, + pub name: std::sync::Arc, /// A list of Vertex pub vertices: Vec, /// A list of indices that dictates the order that vertices appear @@ -106,10 +106,8 @@ pub struct Object { pub instances: Vec, /// instance buffer pub instance_buffer: wgpu::Buffer, - /// Dictates the size of your object in pixels + /// Dictates the size of your object in relation to the world pub size: glm::Vec3, - /// Dictates the scale of your object. Which by default it's 1,1,1 where the screen is size of 2 - pub scale: glm::Vec3, /// Dictates the position of your object in pixels pub position: glm::Vec3, /// Dictates the rotation of your object @@ -128,16 +126,14 @@ pub struct Object { /// Transformation matrix, but inversed pub inverse_transformation_matrix: crate::uniform_type::Matrix, /// The main color of your object - pub uniform_color: crate::uniform_type::Array4, - /// The color of your object that is sent to gpu pub color: crate::uniform_type::Array4, /// A struct making it easier to manipulate specific parts of shader pub shader_builder: crate::objects::ShaderBuilder, /// Shader settings pub shader_settings: ShaderSettings, /// Camera have any effect on the object? - pub camera_effect: bool, - /// Uniform Buffers to be sent to GPU + pub camera_effect: Option>, + /// Uniform Buffers to be sent to GPU. These are raw and not compiled for GPU yet pub uniform_buffers: Vec, /// Should be rendered or not pub is_visible: bool, @@ -148,17 +144,17 @@ unsafe impl Send for Object {} unsafe impl Sync for Object {} /// Extra settings to customize objects on time of creation -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone)] pub struct ObjectSettings { /// Should it be affected by camera? - pub camera_effect: bool, + pub camera_effect: Option>, /// Shader Settings pub shader_settings: ShaderSettings, } impl Default for ObjectSettings { fn default() -> Self { Self { - camera_effect: true, + camera_effect: Some("main".into()), shader_settings: ShaderSettings::default(), } } @@ -597,6 +593,8 @@ pub trait StringBufferTrait { fn as_str(&self) -> &str; /// Returns the string as [`String`] fn as_string(&self) -> String; + /// Returns Arc for ease of computation + fn as_arc(&self) -> std::sync::Arc; } impl StringBufferTrait for String { @@ -606,6 +604,9 @@ impl StringBufferTrait for String { fn as_string(&self) -> String { self.clone() } + fn as_arc(&self) -> std::sync::Arc { + self.as_str().into() + } } impl StringBuffer for String {} impl StringBufferTrait for &str { @@ -615,6 +616,9 @@ impl StringBufferTrait for &str { fn as_string(&self) -> String { self.to_string() } + fn as_arc(&self) -> std::sync::Arc { + self.as_str().into() + } } impl StringBuffer for &str {} diff --git a/src/objects.rs b/src/objects.rs index 221641c..bf3bf7c 100644 --- a/src/objects.rs +++ b/src/objects.rs @@ -42,7 +42,8 @@ impl Renderer { ), ])?; - let shader_source = ShaderBuilder::new(DEFAULT_SHADER.to_string(), settings.camera_effect); + let shader_source = + ShaderBuilder::new(DEFAULT_SHADER.to_string(), settings.camera_effect.clone()); let shader = self.build_shader( name.as_str(), @@ -67,7 +68,7 @@ impl Renderer { let instance_buffer = self.build_instance(vec![instance.to_raw()]); Ok(Object { - name: name.as_string(), + name: name.as_arc(), vertices, indices, pipeline: Pipeline { @@ -79,8 +80,7 @@ impl Renderer { instances: vec![instance], instance_buffer, uniform_layout: uniform.1, - size: glm::vec3(100f32, 100f32, 100f32), - scale: glm::vec3(1f32, 1f32, 1f32), + size: glm::vec3(1f32, 1f32, 1f32), position: glm::vec3(0f32, 0f32, 0f32), rotation: glm::vec3(0f32, 0f32, 0f32), changed: false, @@ -90,9 +90,6 @@ impl Renderer { inverse_transformation_matrix: Matrix::from_im(nalgebra_glm::transpose( &nalgebra_glm::inverse(&DEFAULT_MATRIX_4.to_im()), )), - uniform_color: crate::uniform_type::Array4 { - data: crate::utils::default_resources::DEFAULT_COLOR, - }, color: crate::uniform_type::Array4 { data: crate::utils::default_resources::DEFAULT_COLOR, }, @@ -129,13 +126,6 @@ impl ObjectStorage { renderer.build_object(name.clone(), vertices, indices, settings)?, )?; - /*self.update_object(name, |object| { - object.scale(1f32, 1f32, 1f32); - object.position( - 0f32, 0f32, 0f32 - ); - }); */ - Ok(()) } @@ -172,7 +162,7 @@ impl ObjectStorage { impl Object { /// Sets the name of the object pub fn set_name(&mut self, name: impl StringBuffer) { - self.name = name.as_string(); + self.name = name.as_arc(); } /// Scales an object. e.g. 2.0 doubles the size and 0.5 halves @@ -304,22 +294,6 @@ impl Object { Ok(()) } - /// Changes the main color of the object hat is sent to GPU. If textures exist, the color of textures will change - pub fn set_uniform_color( - &mut self, - red: f32, - green: f32, - blue: f32, - alpha: f32, - ) -> eyre::Result<()> { - self.uniform_color = Array4 { - data: [red, green, blue, alpha], - }; - self.changed = true; - - Ok(()) - } - /// Changes the render order of the Object. /// /// Objects with higher number get rendered later and appear "on top" when occupying the same space @@ -402,7 +376,7 @@ impl Object { /// Update and apply changes done to the shader pub fn update_shader(&mut self, renderer: &mut Renderer) -> eyre::Result<()> { let updated_shader = renderer.build_shader( - self.name.as_str(), + self.name.as_ref(), self.shader_builder.shader.clone(), Some(&self.uniform_layout), self.shader_settings, @@ -418,13 +392,13 @@ impl Object { renderer: &mut Renderer, ) -> eyre::Result { let updated_shader = renderer.build_shader( - self.name.as_str(), + self.name.as_ref(), self.shader_builder.shader.clone(), Some(&self.uniform_layout), self.shader_settings, )?; let updated_shader2 = renderer.build_shader( - self.name.as_str(), + self.name.as_ref(), self.shader_builder.shader.clone(), Some(&self.uniform_layout), self.shader_settings, @@ -442,7 +416,7 @@ impl Object { self.position_matrix * self.rotation_matrix * self.scale_matrix, ), ); - self.uniform_buffers[1] = renderer.build_uniform_buffer_part("Color", self.uniform_color); + self.uniform_buffers[1] = renderer.build_uniform_buffer_part("Color", self.color); let updated_buffer = renderer.build_uniform_buffer(&self.uniform_buffers)?; @@ -463,7 +437,7 @@ impl Object { self.position_matrix * self.rotation_matrix * self.scale_matrix, ), ); - self.uniform_buffers[1] = renderer.build_uniform_buffer_part("Color", self.uniform_color); + self.uniform_buffers[1] = renderer.build_uniform_buffer_part("Color", self.color); let updated_buffer = renderer.build_uniform_buffer(&self.uniform_buffers)?; let updated_buffer2 = renderer.build_uniform_buffer(&self.uniform_buffers)?; @@ -533,23 +507,21 @@ impl Object { } /// Configuration type for ShaderBuilder -pub type ShaderConfigs = Vec<(String, Box String>)>; +pub type ShaderConfigs = Vec<(String, Box>) -> String>)>; /// Helps with building and updating shader code pub struct ShaderBuilder { /// the shader itself pub shader: String, /// Should the camera effect be applied - pub camera_effect: bool, + pub camera_effect: Option>, /// configurations to be applied to the shader - /// - /// the way it works is: `("key to look for", ("shader code with camera effects", "shader code without camera effects"))` pub configs: ShaderConfigs, } impl ShaderBuilder { /// Creates a new shader builder - pub fn new(shader_source: String, camera_effect: bool) -> Self { + pub fn new(shader_source: String, camera_effect: Option>) -> Self { let mut shader_builder = Self { shader: shader_source, camera_effect, @@ -557,9 +529,8 @@ impl ShaderBuilder { ( "//@CAMERA_STRUCT".to_string(), Box::new(|camera_effect| { - if camera_effect { - r#" - struct CameraUniforms { + if camera_effect.is_some() { + r#"struct CameraUniforms { camera_matrix: mat4x4, }; @group(1) @binding(0) @@ -573,7 +544,7 @@ impl ShaderBuilder { ( "//@CAMERA_VERTEX".to_string(), Box::new(|camera_effect| { - if camera_effect { + if camera_effect.is_some() { r#"out.position = camera_uniform.camera_matrix * model_matrix * (transform_uniform.transform_matrix * vec4(input.position, 1.0));"# .to_string() } else { @@ -591,7 +562,7 @@ impl ShaderBuilder { /// Builds the shader with the configuration defined pub fn build(&mut self) { for i in &self.configs { - self.shader = self.shader.replace(&i.0, &i.1(self.camera_effect)); + self.shader = self.shader.replace(&i.0, &i.1(self.camera_effect.clone())); } } } diff --git a/src/render.rs b/src/render.rs index a919f80..5bf844a 100644 --- a/src/render.rs +++ b/src/render.rs @@ -293,13 +293,26 @@ impl Renderer { render_pass.set_bind_group(0, &default_data.0, &[]); render_pass.set_pipeline(&default_data.1); - render_pass.set_bind_group(1, &camera.get("main").unwrap().uniform_data, &[]); // sort the object list in descending render order let mut object_list: Vec<_> = objects.iter().collect(); object_list.sort_by(|(_, a), (_, b)| a.render_order.cmp(&b.render_order).reverse()); for (_, i) in object_list { + if let Some(camera_data) = i.camera_effect.as_ref() { + render_pass.set_bind_group( + 1, + &camera.get(camera_data.as_ref()).unwrap().uniform_data, + &[], + ); + } else { + render_pass.set_bind_group( + 1, + &camera.get("main".into()).unwrap().uniform_data, + &[], + ); + } + if i.is_visible { let vertex_buffer = get_pipeline_vertex_buffer(&i.pipeline.vertex_buffer, objects); let shader = get_pipeline_shader(&i.pipeline.shader, objects); diff --git a/src/window.rs b/src/window.rs index 9fa1643..4adb805 100644 --- a/src/window.rs +++ b/src/window.rs @@ -234,9 +234,11 @@ impl Engine { ); }); - camera - .update_view_projection(&mut renderer) - .expect("Couldn't update camera"); + for camera_value in camera.values_mut() { + camera_value + .update_view_projection(&mut renderer) + .expect("Couldn't update camera"); + } objects.iter_mut().for_each(|i| { if i.1.changed { i.1.update(&mut renderer).expect("Couldn't update objects");