diff --git a/src/bin/pumpkin.rs b/src/bin/pumpkin.rs index 7326921..3248a41 100644 --- a/src/bin/pumpkin.rs +++ b/src/bin/pumpkin.rs @@ -1,5 +1,4 @@ use glam::{Mat4, Vec3, Vec4}; -use rand::Rng; use sdl2::event::Event; use sdl2::keyboard::{Keycode, Scancode}; @@ -129,6 +128,43 @@ where P: AsRef RenderableModel::from_iqm (&model) } +struct ShaderClosure { + program: ShaderProgram, + uniforms: HashMap , + attributes: HashMap >, +} + +struct BorrowedShaderVars <'a> { + unis: &'a HashMap , + attrs: &'a HashMap >, +} + +impl ShaderClosure { + pub fn new ( + program: ShaderProgram, + uniforms: HashMap , + attributes: HashMap > + ) -> Self + { + Self { + program, + uniforms, + attributes, + } + } + + pub fn with (&self, callback: F) + where F: Fn (BorrowedShaderVars) + { + self.program.use_program (); + + callback (BorrowedShaderVars { + unis: &self.uniforms, + attrs: &self.attributes, + }); + } +} + fn main () { let sdl_context = sdl2::init ().unwrap (); let video_subsystem = sdl_context.video ().unwrap (); @@ -171,6 +207,18 @@ fn main () { ShaderProgram::new (&vert_shader, &frag_shader).unwrap () }; + let attrs = shader_program.get_attribute_locations (vec! [ + "pos", + "uv", + "normal", + ].into_iter ()); + + let shadow_attrs = shadow_shader.get_attribute_locations (vec! [ + "pos", + "uv", + "normal", + ].into_iter ()); + let uni_lookup: HashMap <_, &str> = HashMap::from_iter ({ use uniforms::*; vec! [ @@ -204,17 +252,12 @@ fn main () { unis }; - let attrs = shader_program.get_attribute_locations (vec! [ - "pos", - "uv", - "normal", - ].into_iter ()); + glezz::enable_vertex_attrib_array (attrs ["pos"]); + glezz::enable_vertex_attrib_array (attrs ["uv"]); + glezz::enable_vertex_attrib_array (attrs ["normal"]); - let shadow_attrs = shadow_shader.get_attribute_locations (vec! [ - "pos", - "uv", - "normal", - ].into_iter ()); + let shader_diffuse = ShaderClosure::new (shader_program, unis, attrs); + let shader_shadow = ShaderClosure::new (shadow_shader, shadow_unis, shadow_attrs); let texture = Texture::from_file ("sky.png"); texture.bind (); @@ -275,10 +318,6 @@ fn main () { (colors, grass_index.unwrap ()) }; - glezz::enable_vertex_attrib_array (attrs ["pos"]); - glezz::enable_vertex_attrib_array (attrs ["uv"]); - glezz::enable_vertex_attrib_array (attrs ["normal"]); - glezz::enable (gl::DEPTH_TEST); glezz::enable (gl::TEXTURE_2D); @@ -343,10 +382,12 @@ fn main () { let world_model_mat = Mat4::identity (); - { - use uniforms::*; + use uniforms::*; + + shader_diffuse.with (|shader_vars| { + let unis = shader_vars.unis; + let attrs = shader_vars.attrs; - shader_program.use_program (); glezz::disable (gl::STENCIL_TEST); glezz::front_face (gl::CW); @@ -398,25 +439,34 @@ fn main () { gl::DepthMask (0); gl::StencilMask (1); } - shadow_shader.use_program (); + }); + + shader_shadow.with (|shader_vars| { + let unis = shader_vars.unis; + let attrs = shader_vars.attrs; let view_mat = view_mat * shadow_mat; let mvp = view_mat * pumpkin_model_mat; - glezz::uniform_matrix_4fv (shadow_unis [&MVP], &mvp); + glezz::uniform_matrix_4fv (unis [&MVP], &mvp); - mesh_pumpkin.draw_all (&shadow_attrs, |_| true); + mesh_pumpkin.draw_all (&attrs, |_| true); let mvp = view_mat * world_model_mat; - glezz::uniform_matrix_4fv (shadow_unis [&MVP], &mvp); + glezz::uniform_matrix_4fv (unis [&MVP], &mvp); - mesh_pitch.draw_all (&shadow_attrs, |i| i != grass_index); + mesh_pitch.draw_all (&attrs, |i| i != grass_index); unsafe { gl::ColorMask (255, 255, 255, 255); gl::DepthMask (1); } - shader_program.use_program (); + }); + + shader_diffuse.with (|shader_vars| { + let unis = shader_vars.unis; + let attrs = shader_vars.attrs; + glezz::front_face (gl::CW); let inverse_pumpkin = pumpkin_model_mat.inverse (); @@ -447,7 +497,7 @@ fn main () { } glezz::uniform_3fv (unis [&OBJECT_SPACE_LIGHT], &object_space_light); mesh_pitch.draw (&attrs, grass_index); - } + }); window.gl_swap_window (); diff --git a/src/shader.rs b/src/shader.rs index 0eaf51f..a6ef9e6 100644 --- a/src/shader.rs +++ b/src/shader.rs @@ -119,6 +119,8 @@ impl ShaderProgram { } } + // 'use' is a keyword + pub fn use_program (&self) { unsafe { gl::UseProgram (self.id);