diff --git a/ROADMAP.md b/ROADMAP.md index 0fe64fc491..287fc8652d 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -11,6 +11,7 @@ Here is the current list of planned features. All items are sorted in approximat * Physically based rendering * Skeletal animation * Macro to produce vertex buffer attributes (and maybe descriptors) from structs + * Add runtime type safety to uniform bindings (and maybe compile time) * Dynamic / user defined shaders * consider using shaderc-rs. but this introduces compile complexity and requires other C++ build systems * Input diff --git a/src/render/render_graph_2/mod.rs b/src/render/render_graph_2/mod.rs index c8cb0b3d30..b0d7b87273 100644 --- a/src/render/render_graph_2/mod.rs +++ b/src/render/render_graph_2/mod.rs @@ -12,7 +12,8 @@ mod resource; pub mod resource_name; pub mod resource_provider; pub mod resource_providers; -mod shader; +mod standard_material; +mod uniform; pub use draw_target::*; pub use pass::*; @@ -22,4 +23,5 @@ pub use render_graph::*; pub use renderer::*; pub use resource::*; pub use resource_provider::*; -pub use shader::*; +pub use standard_material::*; +pub use uniform::*; \ No newline at end of file diff --git a/src/render/render_graph_2/standard_material.rs b/src/render/render_graph_2/standard_material.rs new file mode 100644 index 0000000000..bba79b98ae --- /dev/null +++ b/src/render/render_graph_2/standard_material.rs @@ -0,0 +1,110 @@ +use crate::{ + math::Vec4, + render::render_graph_2::{BindType, UniformPropertyType, uniform::{UniformInfo, AsUniforms, GetBytes}}, +}; + +use zerocopy::AsBytes; + +pub struct StandardMaterial { + pub albedo: Vec4, +} + + +// create this from a derive macro +const STANDARD_MATERIAL_UNIFORM_INFO: &[UniformInfo] = &[UniformInfo { + name: "StandardMaterial", + bind_type: BindType::Uniform { + dynamic: false, + // TODO: fill this in with properties + properties: Vec::new(), + }, +}]; + +// these are separate from BindType::Uniform{properties} because they need to be const +const STANDARD_MATERIAL_UNIFORM_LAYOUTS: &[&[UniformPropertyType]] = &[&[]]; + +// const +impl AsUniforms for StandardMaterial { + fn get_uniform_infos(&self) -> &[UniformInfo] { + STANDARD_MATERIAL_UNIFORM_INFO + } + + fn get_uniform_layouts(&self) -> &[&[UniformPropertyType]] { + STANDARD_MATERIAL_UNIFORM_LAYOUTS + } + + fn get_uniform_bytes(&self, name: &str) -> Option> { + match name { + "StandardMaterial" => Some(self.albedo.get_bytes()), + _ => None, + } + } + fn get_uniform_info(&self, name: &str) -> Option<&UniformInfo> { + match name { + "StandardMaterial" => Some(&STANDARD_MATERIAL_UNIFORM_INFO[0]), + _ => None, + } + } + + // fn iter_properties(&self) -> std::slice::Iter<&'static str> { + // STANDARD_MATERIAL_PROPERTIES.iter() + // } + // fn get_property(&self, name: &str) -> Option { + // match name { + // "albedo" => Some(match self.albedo { + // Albedo::Color(color) => ShaderValue::Vec4(color), + // Albedo::Texture(ref texture) => ShaderValue::Texture(texture) + // }), + // _ => None, + // } + // } +} + +// create this from a derive macro +const LOCAL_TO_WORLD_UNIFORM_INFO: &[UniformInfo] = &[UniformInfo { + name: "Object", + bind_type: BindType::Uniform { + dynamic: false, + // TODO: maybe fill this in with properties (vec.push cant be const though) + properties: Vec::new(), + }, +}]; + +// these are separate from BindType::Uniform{properties} because they need to be const +const LOCAL_TO_WORLD_UNIFORM_LAYOUTS: &[&[UniformPropertyType]] = &[&[]]; + +// const ST +impl AsUniforms for bevy_transform::prelude::LocalToWorld { + fn get_uniform_infos(&self) -> &[UniformInfo] { + LOCAL_TO_WORLD_UNIFORM_INFO + } + + fn get_uniform_layouts(&self) -> &[&[UniformPropertyType]] { + LOCAL_TO_WORLD_UNIFORM_LAYOUTS + } + + fn get_uniform_bytes(&self, name: &str) -> Option> { + match name { + "Object" => Some(self.0.to_cols_array_2d().as_bytes().into()), + _ => None, + } + } + fn get_uniform_info(&self, name: &str) -> Option<&UniformInfo> { + match name { + "Object" => Some(&LOCAL_TO_WORLD_UNIFORM_INFO[0]), + _ => None, + } + } + // fn iter_properties(&self) -> std::slice::Iter<&'static str> { + // STANDARD_MATERIAL_PROPERTIES.iter() + // } + // fn get_property(&self, name: &str) -> Option { + // match name { + // "albedo" => Some(match self.albedo { + // Albedo::Color(color) => ShaderValue::Vec4(color), + // Albedo::Texture(ref texture) => ShaderValue::Texture(texture) + // }), + // _ => None, + // } + // } +} diff --git a/src/render/render_graph_2/shader.rs b/src/render/render_graph_2/uniform.rs similarity index 51% rename from src/render/render_graph_2/shader.rs rename to src/render/render_graph_2/uniform.rs index 4b75a1330c..9a35ebc26a 100644 --- a/src/render/render_graph_2/shader.rs +++ b/src/render/render_graph_2/uniform.rs @@ -9,6 +9,63 @@ use crate::{ use legion::storage::Component; use zerocopy::AsBytes; +pub trait GetBytes { + fn get_bytes(&self) -> Vec; + fn get_bytes_ref(&self) -> Option<&[u8]>; +} + +// TODO: might need to add zerocopy to this crate to impl AsBytes for external crates +// impl GetBytes for T where T : AsBytes { +// fn get_bytes(&self) -> Vec { +// self.as_bytes().into() +// } + +// fn get_bytes_ref(&self) -> Option<&[u8]> { +// Some(self.as_bytes()) +// } +// } + +impl GetBytes for Vec4 { + fn get_bytes(&self) -> Vec { + let vec4_array: [f32; 4] = (*self).into(); + vec4_array.as_bytes().into() + } + + fn get_bytes_ref(&self) -> Option<&[u8]> { + None + } +} + +pub trait AsUniforms { + fn get_uniform_infos(&self) -> &[UniformInfo]; + fn get_uniform_info(&self, name: &str) -> Option<&UniformInfo>; + fn get_uniform_layouts(&self) -> &[&[UniformPropertyType]]; + fn get_uniform_bytes(&self, name: &str) -> Option>; + // TODO: support zero-copy uniforms + // fn get_uniform_bytes_ref(&self, name: &str) -> Option<&[u8]>; +} + +// pub struct UniformInfo<'a> { +// pub name: &'a str, +// pub +// } + +pub struct UniformInfo<'a> { + pub name: &'a str, + pub bind_type: BindType, +} + +pub fn uniform_selector(entity: Entity, world: &World) -> Option> +where + T: AsUniforms + Component, +{ + world + .get_component::(entity) + .map(|c| c.map_into(|s| s as &dyn AsUniforms)) +} + +// TODO: Remove these + pub type ShaderUniformSelector = fn(Entity, &World) -> Option>; pub struct ShaderUniforms { @@ -72,162 +129,4 @@ impl ShaderUniforms { None } -} - -pub struct StandardMaterial { - pub albedo: Vec4, -} - -pub trait GetBytes { - fn get_bytes(&self) -> Vec; - fn get_bytes_ref(&self) -> Option<&[u8]>; -} - -// TODO: might need to add zerocopy to this crate to impl AsBytes for external crates -// impl GetBytes for T where T : AsBytes { -// fn get_bytes(&self) -> Vec { -// self.as_bytes().into() -// } - -// fn get_bytes_ref(&self) -> Option<&[u8]> { -// Some(self.as_bytes()) -// } -// } - -impl GetBytes for Vec4 { - fn get_bytes(&self) -> Vec { - let vec4_array: [f32; 4] = (*self).into(); - vec4_array.as_bytes().into() - } - - fn get_bytes_ref(&self) -> Option<&[u8]> { - None - } -} - -pub trait AsUniforms { - fn get_uniform_infos(&self) -> &[UniformInfo]; - fn get_uniform_info(&self, name: &str) -> Option<&UniformInfo>; - fn get_uniform_layouts(&self) -> &[&[UniformPropertyType]]; - fn get_uniform_bytes(&self, name: &str) -> Option>; - // TODO: support zero-copy uniforms - // fn get_uniform_bytes_ref(&self, name: &str) -> Option<&[u8]>; -} - -// pub struct UniformInfo<'a> { -// pub name: &'a str, -// pub -// } - -pub struct UniformInfo<'a> { - pub name: &'a str, - pub bind_type: BindType, -} - -pub fn uniform_selector(entity: Entity, world: &World) -> Option> -where - T: AsUniforms + Component, -{ - world - .get_component::(entity) - .map(|c| c.map_into(|s| s as &dyn AsUniforms)) -} - -// create this from a derive macro -const STANDARD_MATERIAL_UNIFORM_INFO: &[UniformInfo] = &[UniformInfo { - name: "StandardMaterial", - bind_type: BindType::Uniform { - dynamic: false, - // TODO: fill this in with properties - properties: Vec::new(), - }, -}]; - -// these are separate from BindType::Uniform{properties} because they need to be const -const STANDARD_MATERIAL_UNIFORM_LAYOUTS: &[&[UniformPropertyType]] = &[&[]]; - -// const -impl AsUniforms for StandardMaterial { - fn get_uniform_infos(&self) -> &[UniformInfo] { - STANDARD_MATERIAL_UNIFORM_INFO - } - - fn get_uniform_layouts(&self) -> &[&[UniformPropertyType]] { - STANDARD_MATERIAL_UNIFORM_LAYOUTS - } - - fn get_uniform_bytes(&self, name: &str) -> Option> { - match name { - "StandardMaterial" => Some(self.albedo.get_bytes()), - _ => None, - } - } - fn get_uniform_info(&self, name: &str) -> Option<&UniformInfo> { - match name { - "StandardMaterial" => Some(&STANDARD_MATERIAL_UNIFORM_INFO[0]), - _ => None, - } - } - - // fn iter_properties(&self) -> std::slice::Iter<&'static str> { - // STANDARD_MATERIAL_PROPERTIES.iter() - // } - // fn get_property(&self, name: &str) -> Option { - // match name { - // "albedo" => Some(match self.albedo { - // Albedo::Color(color) => ShaderValue::Vec4(color), - // Albedo::Texture(ref texture) => ShaderValue::Texture(texture) - // }), - // _ => None, - // } - // } -} - -// create this from a derive macro -const LOCAL_TO_WORLD_UNIFORM_INFO: &[UniformInfo] = &[UniformInfo { - name: "Object", - bind_type: BindType::Uniform { - dynamic: false, - // TODO: maybe fill this in with properties (vec.push cant be const though) - properties: Vec::new(), - }, -}]; - -// these are separate from BindType::Uniform{properties} because they need to be const -const LOCAL_TO_WORLD_UNIFORM_LAYOUTS: &[&[UniformPropertyType]] = &[&[]]; - -// const ST -impl AsUniforms for bevy_transform::prelude::LocalToWorld { - fn get_uniform_infos(&self) -> &[UniformInfo] { - LOCAL_TO_WORLD_UNIFORM_INFO - } - - fn get_uniform_layouts(&self) -> &[&[UniformPropertyType]] { - LOCAL_TO_WORLD_UNIFORM_LAYOUTS - } - - fn get_uniform_bytes(&self, name: &str) -> Option> { - match name { - "Object" => Some(self.0.to_cols_array_2d().as_bytes().into()), - _ => None, - } - } - fn get_uniform_info(&self, name: &str) -> Option<&UniformInfo> { - match name { - "Object" => Some(&LOCAL_TO_WORLD_UNIFORM_INFO[0]), - _ => None, - } - } - // fn iter_properties(&self) -> std::slice::Iter<&'static str> { - // STANDARD_MATERIAL_PROPERTIES.iter() - // } - // fn get_property(&self, name: &str) -> Option { - // match name { - // "albedo" => Some(match self.albedo { - // Albedo::Color(color) => ShaderValue::Vec4(color), - // Albedo::Texture(ref texture) => ShaderValue::Texture(texture) - // }), - // _ => None, - // } - // } -} +} \ No newline at end of file