diff --git a/crates/geng-asset/src/lib.rs b/crates/geng-asset/src/lib.rs index ef4a41e7..1be47209 100644 --- a/crates/geng-asset/src/lib.rs +++ b/crates/geng-asset/src/lib.rs @@ -23,7 +23,7 @@ struct ManagerImpl { window: geng_window::Window, #[cfg(feature = "audio")] audio: geng_audio::Audio, - shader_lib: shader::Library, + shader_lib: Rc, hot_reload_enabled: bool, } @@ -36,6 +36,7 @@ impl Manager { pub fn new( window: &geng_window::Window, #[cfg(feature = "audio")] audio: &geng_audio::Audio, + shader_lib: Rc, hot_reload: bool, ) -> Self { Self { @@ -44,7 +45,7 @@ impl Manager { ugli: window.ugli().clone(), #[cfg(feature = "audio")] audio: audio.clone(), - shader_lib: shader::Library::new(window.ugli(), true, None), + shader_lib, hot_reload_enabled: hot_reload, }), } diff --git a/crates/ugli/src/lib.rs b/crates/ugli/src/lib.rs index 8d8fe2a6..52bb6dd9 100644 --- a/crates/ugli/src/lib.rs +++ b/crates/ugli/src/lib.rs @@ -68,10 +68,13 @@ macro_rules! uniforms { ($name:ident : $value:expr) => { $crate::SingleUniform::new(stringify!($name), $value) }; - ($name:ident : $value:expr, $($names:ident : $values:expr),+) => { - ($crate::uniforms!($name : $value), $crate::uniforms!($($names : $values),+)) + ($name:literal : $value:expr) => { + $crate::SingleUniform::new($name, $value) }; - ($($name:ident : $value:expr),*,) => { - $crate::uniforms!($($name : $value),*) + ($($name:ident)?$($str_name:literal)? : $value:expr, $($($names:ident)?$($str_names:literal)? $([$indices: literal])? : $values:expr),+) => { + ($crate::uniforms!($($name)?$($str_name)? : $value), $crate::uniforms!($($($names)?$($str_names)? : $values),+)) + }; + ($($($name:ident)?$($str_name:literal)? : $value:expr),*,) => { + $crate::uniforms!($($($name)?$($str_name)? : $value),*) } } diff --git a/crates/ugli/src/uniform/mod.rs b/crates/ugli/src/uniform/mod.rs index 42b51eda..57e43c7e 100644 --- a/crates/ugli/src/uniform/mod.rs +++ b/crates/ugli/src/uniform/mod.rs @@ -87,6 +87,81 @@ impl Uniform for [[f32; 4]; 4] { } } +impl Uniform for &[[[f32; 2]; 2]] { + fn apply(&self, gl: &raw::Context, info: &UniformInfo) { + gl.uniform_matrix2fv( + &info.location, + self.len() as _, + raw::FALSE, + &self + .iter() + .flat_map(|mat| unsafe { mem::transmute::<&[[f32; 2]; 2], &[f32; 2 * 2]>(mat) }) + .copied() + .collect::>(), + ); + } +} + +impl Uniform for &[[[f32; 3]; 3]] { + fn apply(&self, gl: &raw::Context, info: &UniformInfo) { + gl.uniform_matrix3fv( + &info.location, + self.len() as _, + raw::FALSE, + &self + .iter() + .flat_map(|mat| unsafe { mem::transmute::<&[[f32; 3]; 3], &[f32; 3 * 3]>(mat) }) + .copied() + .collect::>(), + ); + } +} + +impl Uniform for &[[[f32; 4]; 4]] { + fn apply(&self, gl: &raw::Context, info: &UniformInfo) { + gl.uniform_matrix4fv( + &info.location, + self.len() as _, + raw::FALSE, + &self + .iter() + .flat_map(|mat| unsafe { mem::transmute::<&[[f32; 4]; 4], &[f32; 4 * 4]>(mat) }) + .copied() + .collect::>(), + ); + } +} + +impl Uniform for Vec<[[f32; 3]; 3]> { + fn apply(&self, gl: &raw::Context, info: &UniformInfo) { + gl.uniform_matrix3fv( + &info.location, + self.len() as _, + raw::FALSE, + &self + .iter() + .flat_map(|mat| unsafe { mem::transmute::<&[[f32; 3]; 3], &[f32; 3 * 3]>(mat) }) + .copied() + .collect::>(), + ); + } +} + +impl Uniform for Vec<[[f32; 4]; 4]> { + fn apply(&self, gl: &raw::Context, info: &UniformInfo) { + gl.uniform_matrix4fv( + &info.location, + self.len() as _, + raw::FALSE, + &self + .iter() + .flat_map(|mat| unsafe { mem::transmute::<&[[f32; 4]; 4], &[f32; 4 * 4]>(mat) }) + .copied() + .collect::>(), + ); + } +} + impl Uniform for mat3 { fn apply(&self, gl: &raw::Context, info: &UniformInfo) { gl.uniform_matrix3fv(&info.location, 1, raw::FALSE, self.as_flat_array()); @@ -99,6 +174,66 @@ impl Uniform for mat4 { } } +impl Uniform for &[mat3] { + fn apply(&self, gl: &raw::Context, info: &UniformInfo) { + gl.uniform_matrix3fv( + &info.location, + self.len() as _, + raw::FALSE, + &self + .iter() + .flat_map(|mat| mat.as_flat_array()) + .copied() + .collect::>(), + ); + } +} + +impl Uniform for &[mat4] { + fn apply(&self, gl: &raw::Context, info: &UniformInfo) { + gl.uniform_matrix4fv( + &info.location, + self.len() as _, + raw::FALSE, + &self + .iter() + .flat_map(|mat| mat.as_flat_array()) + .copied() + .collect::>(), + ); + } +} + +impl Uniform for Vec> { + fn apply(&self, gl: &raw::Context, info: &UniformInfo) { + gl.uniform_matrix3fv( + &info.location, + self.len() as _, + raw::FALSE, + &self + .iter() + .flat_map(|mat| mat.as_flat_array()) + .copied() + .collect::>(), + ); + } +} + +impl Uniform for Vec> { + fn apply(&self, gl: &raw::Context, info: &UniformInfo) { + gl.uniform_matrix4fv( + &info.location, + self.len() as _, + raw::FALSE, + &self + .iter() + .flat_map(|mat| mat.as_flat_array()) + .copied() + .collect::>(), + ); + } +} + impl Uniform for Texture2d

{ fn apply(&self, gl: &raw::Context, info: &UniformInfo) { gl.active_texture(raw::TEXTURE0 + unsafe { UNIFORM_TEXTURE_COUNT } as raw::Enum); diff --git a/crates/ugli/src/uniform/storage.rs b/crates/ugli/src/uniform/storage.rs index fe68ef0b..6837b3eb 100644 --- a/crates/ugli/src/uniform/storage.rs +++ b/crates/ugli/src/uniform/storage.rs @@ -77,6 +77,28 @@ impl Uniforms for (A, B, C, } } +impl<'a, U: Uniforms> Uniforms for &'a [U] { + fn walk_uniforms(&self, visitor: &mut C) + where + C: UniformVisitor, + { + for uniform in *self { + uniform.walk_uniforms(visitor); + } + } +} + +impl Uniforms for Vec { + fn walk_uniforms(&self, visitor: &mut C) + where + C: UniformVisitor, + { + for uniform in self { + uniform.walk_uniforms(visitor); + } + } +} + impl Uniforms for Option { fn walk_uniforms(&self, visitor: &mut C) where diff --git a/src/context.rs b/src/context.rs index d3cf937c..3142d9bb 100644 --- a/src/context.rs +++ b/src/context.rs @@ -4,7 +4,7 @@ pub(crate) struct GengImpl { window: Window, #[cfg(feature = "audio")] audio: Audio, - shader_lib: shader::Library, + shader_lib: Rc, pub(crate) draw2d: Rc, asset_manager: asset::Manager, default_font: Rc, @@ -27,6 +27,7 @@ pub struct ContextOptions { pub fixed_delta_time: f64, pub max_delta_time: f64, pub shader_prefix: Option<(String, String)>, + pub shader_lib: HashMap, pub target_ui_resolution: Option>, pub hot_reload: bool, } @@ -48,6 +49,7 @@ impl Default for ContextOptions { fixed_delta_time: 0.05, max_delta_time: 0.1, shader_prefix: None, + shader_lib: HashMap::new(), target_ui_resolution: None, hot_reload: cfg!(debug_assertions), } @@ -75,11 +77,17 @@ impl Geng { setup_panic_handler(); window::run(&options.window.clone(), |window| async move { let ugli = window.ugli().clone(); - let shader_lib = shader::Library::new( + let mut shader_lib = shader::Library::new( &ugli, options.window.antialias, options.shader_prefix.clone(), ); + for (name, source) in options.shader_lib.iter() { + shader_lib.add(name, source); + } + + let shader_lib = Rc::new(shader_lib); + let draw2d = Rc::new(draw2d::Helper::new(&ugli, options.window.antialias)); let default_font = Rc::new(Font::default(window.ugli())); #[cfg(feature = "audio")] @@ -89,12 +97,13 @@ impl Geng { window: window.clone(), #[cfg(feature = "audio")] audio: audio.clone(), - shader_lib, + shader_lib: shader_lib.clone(), draw2d, asset_manager: asset::Manager::new( &window, #[cfg(feature = "audio")] &audio, + shader_lib, options.hot_reload, ), default_font,