🚧 still improving the pass system
parent
9e74609eb1
commit
afb0238c1b
|
@ -152,7 +152,7 @@ struct RenderableArrow {
|
||||||
inv_model_mat: Mat4,
|
inv_model_mat: Mat4,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive (Copy, Clone)]
|
#[derive (Copy, Clone, PartialEq, Eq)]
|
||||||
pub enum FrontFace {
|
pub enum FrontFace {
|
||||||
Cw,
|
Cw,
|
||||||
Ccw,
|
Ccw,
|
||||||
|
@ -171,7 +171,7 @@ impl From <FrontFace> for u32 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive (Copy, Clone)]
|
#[derive (Copy, Clone, PartialEq, Eq)]
|
||||||
pub enum StencilOp {
|
pub enum StencilOp {
|
||||||
Keep,
|
Keep,
|
||||||
Zero,
|
Zero,
|
||||||
|
@ -202,7 +202,7 @@ impl From <StencilOp> for u32 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive (Copy, Clone)]
|
#[derive (Copy, Clone, PartialEq, Eq)]
|
||||||
pub enum StencilFunc {
|
pub enum StencilFunc {
|
||||||
Never,
|
Never,
|
||||||
Always,
|
Always,
|
||||||
|
@ -233,26 +233,30 @@ impl From <StencilFunc> for u32 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive (Copy, Clone, PartialEq, Eq)]
|
||||||
pub struct StencilOpState {
|
pub struct StencilOpState {
|
||||||
sfail: StencilOp,
|
sfail: StencilOp,
|
||||||
dpfail: StencilOp,
|
dpfail: StencilOp,
|
||||||
dppass: StencilOp,
|
dppass: StencilOp,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive (Copy, Clone, PartialEq, Eq)]
|
||||||
pub struct StencilFuncState {
|
pub struct StencilFuncState {
|
||||||
func: StencilFunc,
|
func: StencilFunc,
|
||||||
reference: i32,
|
reference: i32,
|
||||||
mask: u32,
|
mask: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive (Copy, Clone, PartialEq, Eq)]
|
||||||
pub struct StencilState {
|
pub struct StencilState {
|
||||||
op: StencilOpState,
|
op: StencilOpState,
|
||||||
func: StencilFuncState,
|
func: StencilFuncState,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Anything that's None is "unknown"
|
// These are POD where no extra data is needed
|
||||||
|
// to safely use the flags / numbers
|
||||||
|
|
||||||
pub struct GlState {
|
pub struct IsoGlState {
|
||||||
flags: HashMap <u32, bool>,
|
flags: HashMap <u32, bool>,
|
||||||
front_face: Option <FrontFace>,
|
front_face: Option <FrontFace>,
|
||||||
stencil: Option <StencilState>,
|
stencil: Option <StencilState>,
|
||||||
|
@ -262,83 +266,174 @@ pub struct GlState {
|
||||||
stencil_mask: Option <u32>,
|
stencil_mask: Option <u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::default::Default for IsoGlState {
|
||||||
|
fn default () -> Self {
|
||||||
|
Self {
|
||||||
|
flags: hashmap! {},
|
||||||
|
front_face: None,
|
||||||
|
stencil: None,
|
||||||
|
color_mask: None,
|
||||||
|
depth_mask: None,
|
||||||
|
stencil_mask: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// These are POD IDs or hashes of non-POD data
|
||||||
|
|
||||||
|
pub struct NonIsoGlState {
|
||||||
|
shader_id: Option <u32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::default::Default for NonIsoGlState {
|
||||||
|
fn default () -> Self {
|
||||||
|
Self {
|
||||||
|
shader_id: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct GlState {
|
||||||
|
iso: IsoGlState,
|
||||||
|
non_iso: NonIsoGlState,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::default::Default for GlState {
|
||||||
|
fn default () -> Self {
|
||||||
|
Self {
|
||||||
|
iso: Default::default (),
|
||||||
|
non_iso: Default::default (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Pass <'a> {
|
pub struct Pass <'a> {
|
||||||
|
// In the context of a Pass, "None" means "Don't care"
|
||||||
|
|
||||||
|
iso: IsoGlState,
|
||||||
|
|
||||||
|
// Non-iso state must have its sources here
|
||||||
|
|
||||||
shader: Option <&'a ShaderClosure>,
|
shader: Option <&'a ShaderClosure>,
|
||||||
|
|
||||||
// Anything that's None is "don't care"
|
|
||||||
|
|
||||||
required_state: GlState,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Pass <'_> {
|
impl Pass <'_> {
|
||||||
pub fn apply_slow (&self) {
|
pub fn apply_diff (&self, old_state: &mut IsoGlState) {
|
||||||
let state = &self.required_state;
|
let state = &self.iso;
|
||||||
|
|
||||||
|
let mut flag_elision_count = 0;
|
||||||
|
|
||||||
for (flag, value) in state.flags.iter () {
|
for (flag, value) in state.flags.iter () {
|
||||||
if *value {
|
let old_entry = old_state.flags.entry (*flag);
|
||||||
glezz::enable (*flag);
|
if match &old_entry {
|
||||||
|
hash_map::Entry::Vacant (_) => true,
|
||||||
|
hash_map::Entry::Occupied (o) => o.get () != value,
|
||||||
|
} {
|
||||||
|
if *value {
|
||||||
|
glezz::enable (*flag);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
glezz::disable (*flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
old_entry.or_insert (*value);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
glezz::disable (*flag);
|
flag_elision_count += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if flag_elision_count > 0 {
|
||||||
|
//println! ("Elided {} flags", flag_elision_count);
|
||||||
|
}
|
||||||
|
|
||||||
if let Some (v) = &state.front_face {
|
if let Some (v) = &state.front_face {
|
||||||
glezz::front_face ((*v).into ());
|
if old_state.front_face != state.front_face {
|
||||||
|
glezz::front_face ((*v).into ());
|
||||||
|
old_state.front_face = state.front_face;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//println! ("Elided front_face ()");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some (v) = &state.stencil {
|
if let Some (v) = &state.stencil {
|
||||||
let func = &v.func;
|
if old_state.stencil != state.stencil {
|
||||||
let op = &v.op;
|
let func = &v.func;
|
||||||
|
unsafe {
|
||||||
unsafe {
|
gl::StencilFunc (
|
||||||
gl::StencilFunc (
|
func.func.into (),
|
||||||
func.func.into (),
|
func.reference.into (),
|
||||||
func.reference.into (),
|
func.mask.into ()
|
||||||
func.mask.into ()
|
);
|
||||||
);
|
}
|
||||||
gl::StencilOp (
|
|
||||||
op.sfail.into (),
|
let op = &v.op;
|
||||||
op.dpfail.into (),
|
unsafe {
|
||||||
op.dppass.into ()
|
gl::StencilOp (
|
||||||
);
|
op.sfail.into (),
|
||||||
|
op.dpfail.into (),
|
||||||
|
op.dppass.into ()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//println! ("Elided stencil state");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some ((r, g, b, a)) = &state.color_mask {
|
if let Some ((r, g, b, a)) = &state.color_mask {
|
||||||
unsafe {
|
if old_state.color_mask != state.color_mask {
|
||||||
gl::ColorMask (*r, *g, *b, *a);
|
glezz::color_mask (*r, *g, *b, *a);
|
||||||
|
old_state.color_mask = state.color_mask;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//println! ("Elided color_mask ()");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some (v) = &state.depth_mask {
|
if let Some (v) = &state.depth_mask {
|
||||||
unsafe {
|
if old_state.depth_mask != state.depth_mask {
|
||||||
gl::DepthMask (*v);
|
glezz::depth_mask (*v);
|
||||||
|
old_state.depth_mask = state.depth_mask;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//println! ("Elided depth_mask ()");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some (v) = &state.stencil_mask {
|
if let Some (v) = &state.stencil_mask {
|
||||||
unsafe {
|
if old_state.stencil_mask != state.stencil_mask {
|
||||||
gl::StencilMask (*v);
|
glezz::stencil_mask (*v);
|
||||||
|
old_state.stencil_mask = state.stencil_mask;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//println! ("Elided stencil_mask ()");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with <F> (&self, callback: F)
|
pub fn apply_slow (&self) {
|
||||||
|
let mut iso = IsoGlState::default ();
|
||||||
|
|
||||||
|
self.apply_diff (&mut iso);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with <F> (&self, gl_state: &mut GlState, callback: F)
|
||||||
where F: Fn ()
|
where F: Fn ()
|
||||||
{
|
{
|
||||||
self.apply_slow ();
|
self.apply_diff (&mut gl_state.iso);
|
||||||
callback ();
|
callback ();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_shader <F> (&self, callback: F)
|
pub fn with_shader <F> (&self, gl_state: &mut GlState, callback: F)
|
||||||
where F: Fn (BorrowedShaderVars)
|
where F: Fn (BorrowedShaderVars)
|
||||||
{
|
{
|
||||||
if let Some (s) = self.shader {
|
if let Some (s) = self.shader {
|
||||||
s.with (|shader_vars| {
|
self.apply_diff (&mut gl_state.iso);
|
||||||
self.apply_slow ();
|
s.with (gl_state.non_iso.shader_id, |shader_vars| {
|
||||||
callback (shader_vars);
|
callback (shader_vars);
|
||||||
});
|
});
|
||||||
|
gl_state.non_iso.shader_id = Some (s.get_id ());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
panic! ("Called with_shader on a pass with no shader");
|
panic! ("Called with_shader on a pass with no shader");
|
||||||
|
@ -388,7 +483,7 @@ impl GameGraphics {
|
||||||
let shader_diffuse = ShaderClosure::new (shader_from_files ("shaders/pumpkin-vert.glsl", "shaders/pumpkin-frag.glsl"), &uniform_names, &attr_names);
|
let shader_diffuse = ShaderClosure::new (shader_from_files ("shaders/pumpkin-vert.glsl", "shaders/pumpkin-frag.glsl"), &uniform_names, &attr_names);
|
||||||
let shader_shadow = ShaderClosure::new (shader_from_files ("shaders/shadow-vert.glsl", "shaders/shadow-frag.glsl"), &uniform_names, &attr_names);
|
let shader_shadow = ShaderClosure::new (shader_from_files ("shaders/shadow-vert.glsl", "shaders/shadow-frag.glsl"), &uniform_names, &attr_names);
|
||||||
|
|
||||||
shader_diffuse.with (|shader_vars| {
|
shader_diffuse.with (None, |shader_vars| {
|
||||||
let attrs = shader_vars.attrs;
|
let attrs = shader_vars.attrs;
|
||||||
use renderable_model::attributes::*;
|
use renderable_model::attributes::*;
|
||||||
glezz::enable_vertex_attrib_array (attrs [POS]);
|
glezz::enable_vertex_attrib_array (attrs [POS]);
|
||||||
|
@ -462,6 +557,7 @@ impl GameGraphics {
|
||||||
pub fn draw (
|
pub fn draw (
|
||||||
&self,
|
&self,
|
||||||
state: &WorldState,
|
state: &WorldState,
|
||||||
|
gl_state: &mut GlState,
|
||||||
arrows: &[RenderableArrow]
|
arrows: &[RenderableArrow]
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
@ -500,11 +596,13 @@ impl GameGraphics {
|
||||||
|
|
||||||
let light = Vec3::from ((0.25, -0.125, 1.0)).normalize ();
|
let light = Vec3::from ((0.25, -0.125, 1.0)).normalize ();
|
||||||
|
|
||||||
|
//println! ("Started frame");
|
||||||
|
|
||||||
let passes = vec! [
|
let passes = vec! [
|
||||||
// Clear everything
|
// Clear everything
|
||||||
Pass {
|
Pass {
|
||||||
shader: None,
|
shader: None,
|
||||||
required_state: GlState {
|
iso: IsoGlState {
|
||||||
flags: hashmap! {},
|
flags: hashmap! {},
|
||||||
front_face: None,
|
front_face: None,
|
||||||
stencil: None,
|
stencil: None,
|
||||||
|
@ -516,7 +614,7 @@ impl GameGraphics {
|
||||||
// Draw world
|
// Draw world
|
||||||
Pass {
|
Pass {
|
||||||
shader: Some (&self.shader_diffuse),
|
shader: Some (&self.shader_diffuse),
|
||||||
required_state: GlState {
|
iso: IsoGlState {
|
||||||
flags: hashmap! {
|
flags: hashmap! {
|
||||||
gl::CULL_FACE => true,
|
gl::CULL_FACE => true,
|
||||||
gl::DEPTH_TEST => true,
|
gl::DEPTH_TEST => true,
|
||||||
|
@ -533,7 +631,7 @@ impl GameGraphics {
|
||||||
// Write shadows into stencil buffer
|
// Write shadows into stencil buffer
|
||||||
Pass {
|
Pass {
|
||||||
shader: Some (&self.shader_shadow),
|
shader: Some (&self.shader_shadow),
|
||||||
required_state: GlState {
|
iso: IsoGlState {
|
||||||
flags: hashmap! {
|
flags: hashmap! {
|
||||||
gl::CULL_FACE => true,
|
gl::CULL_FACE => true,
|
||||||
gl::DEPTH_TEST => true,
|
gl::DEPTH_TEST => true,
|
||||||
|
@ -560,7 +658,7 @@ impl GameGraphics {
|
||||||
// Draw lit ground
|
// Draw lit ground
|
||||||
Pass {
|
Pass {
|
||||||
shader: Some (&self.shader_diffuse),
|
shader: Some (&self.shader_diffuse),
|
||||||
required_state: GlState {
|
iso: IsoGlState {
|
||||||
flags: hashmap! {
|
flags: hashmap! {
|
||||||
gl::CULL_FACE => true,
|
gl::CULL_FACE => true,
|
||||||
gl::DEPTH_TEST => true,
|
gl::DEPTH_TEST => true,
|
||||||
|
@ -588,7 +686,7 @@ impl GameGraphics {
|
||||||
// Draw unlit ground
|
// Draw unlit ground
|
||||||
Pass {
|
Pass {
|
||||||
shader: Some (&self.shader_diffuse),
|
shader: Some (&self.shader_diffuse),
|
||||||
required_state: GlState {
|
iso: IsoGlState {
|
||||||
flags: hashmap! {
|
flags: hashmap! {
|
||||||
gl::CULL_FACE => true,
|
gl::CULL_FACE => true,
|
||||||
gl::DEPTH_TEST => true,
|
gl::DEPTH_TEST => true,
|
||||||
|
@ -615,7 +713,7 @@ impl GameGraphics {
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
passes [0].with (|| {
|
passes [0].with (gl_state, || {
|
||||||
glezz::clear_color (1.0f32, 0.0f32, 1.0f32, 1.0f32);
|
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::clear (gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT | gl::STENCIL_BUFFER_BIT);
|
||||||
});
|
});
|
||||||
|
@ -632,7 +730,7 @@ impl GameGraphics {
|
||||||
use uniforms::*;
|
use uniforms::*;
|
||||||
|
|
||||||
// Draw the world except the ground plane
|
// Draw the world except the ground plane
|
||||||
passes [1].with_shader (|shader_vars| {
|
passes [1].with_shader (gl_state, |shader_vars| {
|
||||||
let unis = shader_vars.unis;
|
let unis = shader_vars.unis;
|
||||||
let attrs = shader_vars.attrs;
|
let attrs = shader_vars.attrs;
|
||||||
|
|
||||||
|
@ -688,7 +786,7 @@ impl GameGraphics {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Draw shadows into stencil buffer
|
// Draw shadows into stencil buffer
|
||||||
passes [2].with_shader (|shader_vars| {
|
passes [2].with_shader (gl_state, |shader_vars| {
|
||||||
let unis = shader_vars.unis;
|
let unis = shader_vars.unis;
|
||||||
let attrs = shader_vars.attrs;
|
let attrs = shader_vars.attrs;
|
||||||
|
|
||||||
|
@ -715,7 +813,7 @@ impl GameGraphics {
|
||||||
let object_space_light = make_object_space_vec (&inverse_pumpkin, &light);
|
let object_space_light = make_object_space_vec (&inverse_pumpkin, &light);
|
||||||
|
|
||||||
// Draw unlit ground
|
// Draw unlit ground
|
||||||
passes [3].with_shader (|shader_vars| {
|
passes [3].with_shader (gl_state, |shader_vars| {
|
||||||
let unis = shader_vars.unis;
|
let unis = shader_vars.unis;
|
||||||
let attrs = shader_vars.attrs;
|
let attrs = shader_vars.attrs;
|
||||||
|
|
||||||
|
@ -737,7 +835,7 @@ impl GameGraphics {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Draw lit ground
|
// Draw lit ground
|
||||||
passes [4].with_shader (|shader_vars| {
|
passes [4].with_shader (gl_state, |shader_vars| {
|
||||||
let unis = shader_vars.unis;
|
let unis = shader_vars.unis;
|
||||||
let attrs = shader_vars.attrs;
|
let attrs = shader_vars.attrs;
|
||||||
|
|
||||||
|
@ -771,6 +869,7 @@ fn main () {
|
||||||
let mut state = WorldState::new ();
|
let mut state = WorldState::new ();
|
||||||
|
|
||||||
let graphics = GameGraphics::new ();
|
let graphics = GameGraphics::new ();
|
||||||
|
let mut gl_state = Default::default ();
|
||||||
|
|
||||||
let mut event_pump = sdl_context.event_pump ().unwrap ();
|
let mut event_pump = sdl_context.event_pump ().unwrap ();
|
||||||
'running: loop {
|
'running: loop {
|
||||||
|
@ -848,7 +947,7 @@ fn main () {
|
||||||
|
|
||||||
window.gl_make_current (&gl_ctx).unwrap ();
|
window.gl_make_current (&gl_ctx).unwrap ();
|
||||||
|
|
||||||
graphics.draw (&state, &renderable_arrows);
|
graphics.draw (&state, &mut gl_state, &renderable_arrows);
|
||||||
|
|
||||||
window.gl_swap_window ();
|
window.gl_swap_window ();
|
||||||
|
|
||||||
|
|
18
src/glezz.rs
18
src/glezz.rs
|
@ -79,6 +79,24 @@ pub fn uniform_matrix_4fv (uni: i32, m: &Mat4) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn color_mask (r: u8, g: u8, b: u8, a: u8) {
|
||||||
|
unsafe {
|
||||||
|
gl::ColorMask (r, g, b, a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn depth_mask (v: u8) {
|
||||||
|
unsafe {
|
||||||
|
gl::DepthMask (v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn stencil_mask (v: u32) {
|
||||||
|
unsafe {
|
||||||
|
gl::StencilMask (v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// More abstract things below here
|
// More abstract things below here
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -119,6 +119,10 @@ impl ShaderProgram {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_id (&self) -> u32 {
|
||||||
|
self.id
|
||||||
|
}
|
||||||
|
|
||||||
// 'use' is a keyword
|
// 'use' is a keyword
|
||||||
|
|
||||||
pub fn use_program (&self) {
|
pub fn use_program (&self) {
|
||||||
|
|
|
@ -67,10 +67,19 @@ impl ShaderClosure {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with <F> (&self, callback: F)
|
pub fn get_id (&self) -> u32 {
|
||||||
|
self.program.get_id ()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with <F> (&self, previous_id: Option <u32>, callback: F)
|
||||||
where F: Fn (BorrowedShaderVars)
|
where F: Fn (BorrowedShaderVars)
|
||||||
{
|
{
|
||||||
self.program.use_program ();
|
if previous_id != Some (self.get_id ()) {
|
||||||
|
self.program.use_program ();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//println! ("Elided use_program ()");
|
||||||
|
}
|
||||||
|
|
||||||
callback (BorrowedShaderVars {
|
callback (BorrowedShaderVars {
|
||||||
unis: &self.uniforms,
|
unis: &self.uniforms,
|
||||||
|
|
Loading…
Reference in New Issue