diff --git a/src/bin/pumpkin.rs b/src/bin/pumpkin.rs index 950a72c..e8b9420 100644 --- a/src/bin/pumpkin.rs +++ b/src/bin/pumpkin.rs @@ -256,10 +256,14 @@ pub struct GlState { flags: HashMap , front_face: Option , stencil: Option , + + color_mask: Option <(u8, u8, u8, u8)>, + depth_mask: Option , + stencil_mask: Option , } pub struct Pass <'a> { - shader: &'a ShaderClosure, + shader: Option <&'a ShaderClosure>, // Anything that's None is "don't care" @@ -279,30 +283,44 @@ impl Pass <'_> { } } - match state.front_face { - Some (v) => glezz::front_face (v.into ()), - _ => (), + if let Some (v) = &state.front_face { + glezz::front_face ((*v).into ()); } - match &state.stencil { - Some (v) => { - let func = &v.func; - let op = &v.op; - - unsafe { - gl::StencilFunc ( - func.func.into (), - func.reference.into (), - func.mask.into () - ); - gl::StencilOp ( - op.sfail.into (), - op.dpfail.into (), - op.dppass.into () - ); - } - }, - _ => (), + if let Some (v) = &state.stencil { + let func = &v.func; + let op = &v.op; + + unsafe { + gl::StencilFunc ( + func.func.into (), + func.reference.into (), + func.mask.into () + ); + gl::StencilOp ( + op.sfail.into (), + op.dpfail.into (), + op.dppass.into () + ); + } + } + + if let Some ((r, g, b, a)) = &state.color_mask { + unsafe { + gl::ColorMask (*r, *g, *b, *a); + } + } + + if let Some (v) = &state.depth_mask { + unsafe { + gl::DepthMask (*v); + } + } + + if let Some (v) = &state.stencil_mask { + unsafe { + gl::StencilMask (*v); + } } } } @@ -461,24 +479,41 @@ impl GameGraphics { let light = Vec3::from ((0.25, -0.125, 1.0)).normalize (); - glezz::clear_color (1.0f32, 0.0f32, 1.0f32, 1.0f32); - glezz::clear (gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT | gl::STENCIL_BUFFER_BIT); - let passes = vec! [ + // Clear everything Pass { - shader: &self.shader_diffuse, + shader: None, + required_state: GlState { + flags: hashmap! {}, + front_face: None, + stencil: None, + color_mask: Some ((1, 1, 1, 1)), + depth_mask: Some (1), + stencil_mask: Some (255), + }, + }, + // Draw world + Pass { + shader: Some (&self.shader_diffuse), required_state: GlState { flags: hashmap! { + gl::DEPTH_TEST => true, + gl::TEXTURE_2D => true, gl::STENCIL_TEST => false, }, front_face: Some (FrontFace::Cw), stencil: None, + color_mask: Some ((1, 1, 1, 1)), + depth_mask: Some (1), + stencil_mask: Some (0), }, }, + // Write shadows into stencil buffer Pass { - shader: &self.shader_shadow, + shader: Some (&self.shader_shadow), required_state: GlState { flags: hashmap! { + gl::DEPTH_TEST => true, gl::STENCIL_TEST => true, }, front_face: Some (FrontFace::Ccw), @@ -494,12 +529,18 @@ impl GameGraphics { dppass: StencilOp::Replace, }, }), + color_mask: Some ((0, 0, 0, 0)), + depth_mask: Some (0), + stencil_mask: Some (255), }, }, + // Draw lit ground Pass { - shader: &self.shader_shadow, + shader: Some (&self.shader_diffuse), required_state: GlState { flags: hashmap! { + gl::DEPTH_TEST => true, + gl::TEXTURE_2D => true, gl::STENCIL_TEST => true, }, front_face: Some (FrontFace::Cw), @@ -515,12 +556,18 @@ impl GameGraphics { dppass: StencilOp::Keep, }, }), + color_mask: Some ((1, 1, 1, 1)), + depth_mask: Some (1), + stencil_mask: Some (0), }, }, + // Draw unlit ground Pass { - shader: &self.shader_shadow, + shader: Some (&self.shader_diffuse), required_state: GlState { flags: hashmap! { + gl::DEPTH_TEST => true, + gl::TEXTURE_2D => true, gl::STENCIL_TEST => true, }, front_face: Some (FrontFace::Cw), @@ -536,10 +583,17 @@ impl GameGraphics { dppass: StencilOp::Keep, }, }), + color_mask: Some ((1, 1, 1, 1)), + depth_mask: Some (1), + stencil_mask: Some (0), }, }, ]; + passes [0].apply_slow (); + glezz::clear_color (1.0f32, 0.0f32, 1.0f32, 1.0f32); + glezz::clear (gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT | gl::STENCIL_BUFFER_BIT); + glezz::enable (gl::CULL_FACE); let pumpkin_model_mat = @@ -552,15 +606,12 @@ impl GameGraphics { use uniforms::*; - glezz::enable (gl::DEPTH_TEST); - glezz::enable (gl::TEXTURE_2D); - self.shader_diffuse.with (|shader_vars| { let unis = shader_vars.unis; let attrs = shader_vars.attrs; // Pass 0 - Draw the world except the ground plane - passes [0].apply_slow (); + passes [1].apply_slow (); let mvp = view_mat * pumpkin_model_mat; glezz::uniform_matrix_4fv (unis [&MVP], &mvp); @@ -619,13 +670,8 @@ impl GameGraphics { let unis = shader_vars.unis; let attrs = shader_vars.attrs; - // Pass 1: Draw shadows into stencil buffer - passes [1].apply_slow (); - unsafe { - gl::ColorMask (0, 0, 0, 0); - gl::DepthMask (0); - gl::StencilMask (1); - } + // Draw shadows into stencil buffer + passes [2].apply_slow (); let view_mat = view_mat * shadow_mat; @@ -651,12 +697,8 @@ impl GameGraphics { let unis = shader_vars.unis; let attrs = shader_vars.attrs; - // Pass 2: Draw lit ground - passes [2].apply_slow (); - unsafe { - gl::ColorMask (255, 255, 255, 255); - gl::DepthMask (1); - } + // Draw lit ground + passes [3].apply_slow (); let inverse_pumpkin = pumpkin_model_mat.inverse (); @@ -676,8 +718,8 @@ impl GameGraphics { glezz::uniform_3fv (unis [&OBJECT_SPACE_LIGHT], &Vec3::from ((0.0, 0.0, 0.0))); self.mesh_pitch.draw (attrs, self.grass_index); - // Pass 3: Draw shadowed ground - passes [3].apply_slow (); + // Draw shadowed ground + passes [4].apply_slow (); glezz::uniform_3fv (unis [&OBJECT_SPACE_LIGHT], &object_space_light); self.mesh_pitch.draw (attrs, self.grass_index);