♻️ refactor

main
_ 2020-03-10 12:47:21 +00:00
parent 7f15b34591
commit a6c4ebff39
6 changed files with 375 additions and 366 deletions

View File

@ -1,7 +1,6 @@
#[macro_use] #[macro_use]
extern crate maplit; extern crate maplit;
use float_ord::FloatOrd;
use glam::{Mat4, Quat, Vec3, Vec4}; use glam::{Mat4, Quat, Vec3, Vec4};
use sdl2::event::Event; use sdl2::event::Event;
@ -13,10 +12,9 @@ use std::time::{Duration};
use opengl_rust::*; use opengl_rust::*;
use file::load_small_file; use gl_state::*;
use iqm::Model; use renderable_model::*;
use renderable_model::RenderableModel; use shader::*;
use shader::{ShaderProgram, ShaderObject};
use shader_closure::*; use shader_closure::*;
use texture::Texture; use texture::Texture;
use timestep::TimeStep; use timestep::TimeStep;
@ -190,7 +188,7 @@ struct FlightState {
} }
impl FlightState { impl FlightState {
pub fn handle_event (&mut self, event: &sdl2::event::Event) { pub fn handle_event (&mut self, _event: &sdl2::event::Event) {
} }
@ -202,10 +200,13 @@ impl FlightState {
let nose = airplane.ori.mul_vec3 ((0.0, 1.0, 0.0).into ()); let nose = airplane.ori.mul_vec3 ((0.0, 1.0, 0.0).into ());
let speed = airplane.vel.length (); let speed = airplane.vel.length ();
// Different from nose since planes are always drifting // Different from nose since planes are always drifting
let direction = match speed { let direction = if speed == 0.0 {
0.0 => Vec3::from ((0.0, 0.0, 0.0)), Vec3::from ((0.0, 0.0, 0.0))
_ => airplane.vel * (1.0 / speed), }
else {
airplane.vel * (1.0 / speed)
}; };
let object_space_dir = airplane.ori.conjugate ().mul_vec3 (direction); let object_space_dir = airplane.ori.conjugate ().mul_vec3 (direction);
// Forces // Forces
@ -353,24 +354,6 @@ fn make_object_space_vec (inverse_model_mat: &Mat4, world_space_vec: &Vec3)
Vec3::from ((v4.x (), v4.y (), v4.z ())) Vec3::from ((v4.x (), v4.y (), v4.z ()))
} }
fn renderable_from_iqm_file <P> (filename: P) -> RenderableModel
where P: AsRef <std::path::Path>
{
let data = load_small_file (filename, 1024 * 1024).unwrap ();
let model = Model::from_slice (&data).unwrap ();
RenderableModel::from_iqm (&model)
}
fn shader_from_files <P> (vert: P, frag: P) -> ShaderProgram
where P: AsRef <std::path::Path>
{
let vert_shader = ShaderObject::from_file (gl::VERTEX_SHADER, vert).unwrap ();
let frag_shader = ShaderObject::from_file (gl::FRAGMENT_SHADER, frag).unwrap ();
ShaderProgram::new (&vert_shader, &frag_shader).unwrap ()
}
struct Arrow { struct Arrow {
origin: Vec3, origin: Vec3,
direction: Vec3, direction: Vec3,
@ -383,344 +366,6 @@ struct RenderableArrow {
color: Vec3, color: Vec3,
} }
#[derive (Copy, Clone, PartialEq, Eq)]
pub enum FrontFace {
Cw,
Ccw,
}
impl From <FrontFace> for u32 {
fn from (v: FrontFace) -> Self {
use FrontFace::*;
{
use gl::*;
match v {
Cw => CW,
Ccw => CCW,
}
}
}
}
#[derive (Copy, Clone, PartialEq, Eq)]
pub enum StencilOp {
Keep,
Zero,
Replace,
Incr,
Decr,
Invert,
IncrWrap,
DecrWrap,
}
impl From <StencilOp> for u32 {
fn from (v: StencilOp) -> Self {
use StencilOp::*;
{
use gl::*;
match v {
Keep => KEEP,
Zero => ZERO,
Replace => REPLACE,
Incr => INCR,
Decr => DECR,
Invert => INVERT,
IncrWrap => INCR_WRAP,
DecrWrap => DECR_WRAP,
}
}
}
}
#[derive (Copy, Clone, PartialEq, Eq)]
pub enum StencilFunc {
Never,
Always,
Less,
LessEqual,
Equal,
Greater,
GreaterEqual,
NotEqual,
}
impl From <StencilFunc> for u32 {
fn from (v: StencilFunc) -> Self {
use StencilFunc::*;
{
use gl::*;
match v {
Never => NEVER,
Always => ALWAYS,
Less => LESS,
LessEqual => LEQUAL,
Equal => EQUAL,
Greater => GREATER,
GreaterEqual => GEQUAL,
NotEqual => NOTEQUAL,
}
}
}
}
#[derive (Copy, Clone, PartialEq, Eq)]
pub enum DepthFunc {
Never,
Always,
Less,
LessEqual,
Equal,
Greater,
GreaterEqual,
NotEqual,
}
impl From <DepthFunc> for u32 {
fn from (v: DepthFunc) -> Self {
use DepthFunc::*;
{
use gl::*;
match v {
Never => NEVER,
Always => ALWAYS,
Less => LESS,
LessEqual => LEQUAL,
Equal => EQUAL,
Greater => GREATER,
GreaterEqual => GEQUAL,
NotEqual => NOTEQUAL,
}
}
}
}
#[derive (Copy, Clone, PartialEq, Eq)]
pub struct StencilOpState {
sfail: StencilOp,
dpfail: StencilOp,
dppass: StencilOp,
}
#[derive (Copy, Clone, PartialEq, Eq)]
pub struct StencilFuncState {
func: StencilFunc,
reference: i32,
mask: u32,
}
#[derive (Copy, Clone, PartialEq, Eq)]
pub struct StencilState {
op: StencilOpState,
func: StencilFuncState,
}
// These are POD where no extra data is needed
// to safely use the flags / numbers
pub struct IsoGlState {
shader_id: Option <u32>,
flags: HashMap <u32, bool>,
front_face: Option <FrontFace>,
stencil: Option <StencilState>,
depth_func: Option <DepthFunc>,
color_mask: Option <(u8, u8, u8, u8)>,
depth_mask: Option <u8>,
stencil_mask: Option <u32>,
}
impl std::default::Default for IsoGlState {
fn default () -> Self {
Self {
shader_id: None,
flags: hashmap! {},
front_face: None,
stencil: None,
depth_func: None,
color_mask: None,
depth_mask: None,
stencil_mask: None,
}
}
}
// These are POD IDs or hashes of non-POD data
pub struct NonIsoGlState {
}
impl std::default::Default for NonIsoGlState {
fn default () -> Self {
Self {
}
}
}
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 {
// In the context of a Pass, "None" means "Don't care"
iso: IsoGlState,
}
impl Pass {
pub fn apply_diff (&self, old_state: &mut IsoGlState) {
let state = &self.iso;
let mut flag_elision_count = 0;
for (flag, value) in state.flags.iter () {
let old_entry = old_state.flags.entry (*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 {
flag_elision_count += 1;
}
}
if flag_elision_count > 0 {
//println! ("Elided {} flags", flag_elision_count);
}
if let Some (v) = &state.front_face {
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 old_state.stencil != state.stencil {
let func = &v.func;
unsafe {
gl::StencilFunc (
func.func.into (),
func.reference.into (),
func.mask.into ()
);
}
let op = &v.op;
unsafe {
gl::StencilOp (
op.sfail.into (),
op.dpfail.into (),
op.dppass.into ()
);
}
}
else {
//println! ("Elided stencil state");
}
}
if let Some (v) = &state.depth_func {
if old_state.depth_func != state.depth_func {
glezz::depth_func ((*v).into ());
old_state.depth_func = state.depth_func;
}
else {
//println! ("Elided depth_func ()");
}
}
if let Some ((r, g, b, a)) = &state.color_mask {
if old_state.color_mask != state.color_mask {
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 old_state.depth_mask != state.depth_mask {
glezz::depth_mask (*v);
old_state.depth_mask = state.depth_mask;
}
else {
//println! ("Elided depth_mask ()");
}
}
if let Some (v) = &state.stencil_mask {
if old_state.stencil_mask != state.stencil_mask {
glezz::stencil_mask (*v);
old_state.stencil_mask = state.stencil_mask;
}
else {
//println! ("Elided stencil_mask ()");
}
}
}
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 ()
{
self.apply_diff (&mut gl_state.iso);
callback ();
}
pub fn with_shader <F, S> (
&self,
gl_state: &mut GlState,
shader_component: &S,
callback: F
)
where F: Fn (BorrowedShaderVars), S: ShaderLookup
{
if let Some (s) = self.iso.shader_id {
self.apply_diff (&mut gl_state.iso);
shader_component.lookup (s).with (gl_state.iso.shader_id, |shader_vars| {
callback (shader_vars);
});
gl_state.iso.shader_id = Some (s);
}
else {
panic! ("Called with_shader on a pass with no shader");
}
}
}
pub trait ShaderLookup {
fn lookup <'a> (&'a self, id: u32) -> &'a ShaderClosure;
}
struct GameGraphics { struct GameGraphics {
passes: Vec <Pass>, passes: Vec <Pass>,
@ -1133,7 +778,7 @@ impl GameGraphics {
let gunmetal_grey = color_from_255 ((133.0, 149.0, 161.0)); let gunmetal_grey = color_from_255 ((133.0, 149.0, 161.0));
glezz::uniform_3fv (unis [&ALBEDO], &gunmetal_grey); glezz::uniform_3fv (unis [&ALBEDO], &gunmetal_grey);
self.mesh_airplane.draw_all (attrs, |i| { self.mesh_airplane.draw_all (attrs, |_i| {
true true
}); });

338
src/gl_state.rs Normal file
View File

@ -0,0 +1,338 @@
use std::collections::*;
use crate::glezz;
use crate::shader_closure::*;
#[derive (Copy, Clone, PartialEq, Eq)]
pub enum FrontFace {
Cw,
Ccw,
}
impl From <FrontFace> for u32 {
fn from (v: FrontFace) -> Self {
use FrontFace::*;
{
use gl::*;
match v {
Cw => CW,
Ccw => CCW,
}
}
}
}
#[derive (Copy, Clone, PartialEq, Eq)]
pub enum StencilOp {
Keep,
Zero,
Replace,
Incr,
Decr,
Invert,
IncrWrap,
DecrWrap,
}
impl From <StencilOp> for u32 {
fn from (v: StencilOp) -> Self {
use StencilOp::*;
{
use gl::*;
match v {
Keep => KEEP,
Zero => ZERO,
Replace => REPLACE,
Incr => INCR,
Decr => DECR,
Invert => INVERT,
IncrWrap => INCR_WRAP,
DecrWrap => DECR_WRAP,
}
}
}
}
#[derive (Copy, Clone, PartialEq, Eq)]
pub enum StencilFunc {
Never,
Always,
Less,
LessEqual,
Equal,
Greater,
GreaterEqual,
NotEqual,
}
impl From <StencilFunc> for u32 {
fn from (v: StencilFunc) -> Self {
use StencilFunc::*;
{
use gl::*;
match v {
Never => NEVER,
Always => ALWAYS,
Less => LESS,
LessEqual => LEQUAL,
Equal => EQUAL,
Greater => GREATER,
GreaterEqual => GEQUAL,
NotEqual => NOTEQUAL,
}
}
}
}
#[derive (Copy, Clone, PartialEq, Eq)]
pub enum DepthFunc {
Never,
Always,
Less,
LessEqual,
Equal,
Greater,
GreaterEqual,
NotEqual,
}
impl From <DepthFunc> for u32 {
fn from (v: DepthFunc) -> Self {
use DepthFunc::*;
{
use gl::*;
match v {
Never => NEVER,
Always => ALWAYS,
Less => LESS,
LessEqual => LEQUAL,
Equal => EQUAL,
Greater => GREATER,
GreaterEqual => GEQUAL,
NotEqual => NOTEQUAL,
}
}
}
}
#[derive (Copy, Clone, PartialEq, Eq)]
pub struct StencilOpState {
pub sfail: StencilOp,
pub dpfail: StencilOp,
pub dppass: StencilOp,
}
#[derive (Copy, Clone, PartialEq, Eq)]
pub struct StencilFuncState {
pub func: StencilFunc,
pub reference: i32,
pub mask: u32,
}
#[derive (Copy, Clone, PartialEq, Eq)]
pub struct StencilState {
pub op: StencilOpState,
pub func: StencilFuncState,
}
// These are POD where no extra data is needed
// to safely use the flags / numbers
pub struct IsoGlState {
pub shader_id: Option <u32>,
pub flags: HashMap <u32, bool>,
pub front_face: Option <FrontFace>,
pub stencil: Option <StencilState>,
pub depth_func: Option <DepthFunc>,
pub color_mask: Option <(u8, u8, u8, u8)>,
pub depth_mask: Option <u8>,
pub stencil_mask: Option <u32>,
}
impl std::default::Default for IsoGlState {
fn default () -> Self {
Self {
shader_id: None,
flags: hashmap! {},
front_face: None,
stencil: None,
depth_func: None,
color_mask: None,
depth_mask: None,
stencil_mask: None,
}
}
}
// These are POD IDs or hashes of non-POD data
pub struct NonIsoGlState {
}
impl std::default::Default for NonIsoGlState {
fn default () -> Self {
Self {
}
}
}
pub struct GlState {
pub iso: IsoGlState,
pub non_iso: NonIsoGlState,
}
impl std::default::Default for GlState {
fn default () -> Self {
Self {
iso: Default::default (),
non_iso: Default::default (),
}
}
}
pub struct Pass {
// In the context of a Pass, "None" means "Don't care"
pub iso: IsoGlState,
}
impl Pass {
pub fn apply_diff (&self, old_state: &mut IsoGlState) {
let state = &self.iso;
let mut flag_elision_count = 0;
for (flag, value) in state.flags.iter () {
let old_entry = old_state.flags.entry (*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 {
flag_elision_count += 1;
}
}
if flag_elision_count > 0 {
//println! ("Elided {} flags", flag_elision_count);
}
if let Some (v) = &state.front_face {
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 old_state.stencil != state.stencil {
let func = &v.func;
unsafe {
gl::StencilFunc (
func.func.into (),
func.reference.into (),
func.mask.into ()
);
}
let op = &v.op;
unsafe {
gl::StencilOp (
op.sfail.into (),
op.dpfail.into (),
op.dppass.into ()
);
}
}
else {
//println! ("Elided stencil state");
}
}
if let Some (v) = &state.depth_func {
if old_state.depth_func != state.depth_func {
glezz::depth_func ((*v).into ());
old_state.depth_func = state.depth_func;
}
else {
//println! ("Elided depth_func ()");
}
}
if let Some ((r, g, b, a)) = &state.color_mask {
if old_state.color_mask != state.color_mask {
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 old_state.depth_mask != state.depth_mask {
glezz::depth_mask (*v);
old_state.depth_mask = state.depth_mask;
}
else {
//println! ("Elided depth_mask ()");
}
}
if let Some (v) = &state.stencil_mask {
if old_state.stencil_mask != state.stencil_mask {
glezz::stencil_mask (*v);
old_state.stencil_mask = state.stencil_mask;
}
else {
//println! ("Elided stencil_mask ()");
}
}
}
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 ()
{
self.apply_diff (&mut gl_state.iso);
callback ();
}
pub fn with_shader <F, S> (
&self,
gl_state: &mut GlState,
shader_component: &S,
callback: F
)
where F: Fn (BorrowedShaderVars), S: ShaderLookup
{
if let Some (s) = self.iso.shader_id {
self.apply_diff (&mut gl_state.iso);
shader_component.lookup (s).with (gl_state.iso.shader_id, |shader_vars| {
callback (shader_vars);
});
gl_state.iso.shader_id = Some (s);
}
else {
panic! ("Called with_shader on a pass with no shader");
}
}
}

View File

@ -1,8 +1,12 @@
#[macro_use] #[macro_use]
extern crate iota; extern crate iota;
#[macro_use]
extern crate maplit;
pub mod file; pub mod file;
pub mod glezz; pub mod glezz;
pub mod gl_state;
pub mod gpu_buffers; pub mod gpu_buffers;
pub mod iqm; pub mod iqm;
pub mod renderable_model; pub mod renderable_model;

View File

@ -142,3 +142,12 @@ impl RenderableModel {
self.meshes.len () self.meshes.len ()
} }
} }
pub fn renderable_from_iqm_file <P> (filename: P) -> RenderableModel
where P: AsRef <std::path::Path>
{
let data = crate::file::load_small_file (filename, 1024 * 1024).unwrap ();
let model = crate::iqm::Model::from_slice (&data).unwrap ();
RenderableModel::from_iqm (&model)
}

View File

@ -197,3 +197,12 @@ impl Drop for ShaderProgram {
} }
} }
} }
pub fn shader_from_files <P> (vert: P, frag: P) -> ShaderProgram
where P: AsRef <std::path::Path>
{
let vert_shader = ShaderObject::from_file (gl::VERTEX_SHADER, vert).unwrap ();
let frag_shader = ShaderObject::from_file (gl::FRAGMENT_SHADER, frag).unwrap ();
ShaderProgram::new (&vert_shader, &frag_shader).unwrap ()
}

View File

@ -87,3 +87,7 @@ impl ShaderClosure {
}); });
} }
} }
pub trait ShaderLookup {
fn lookup <'a> (&'a self, id: u32) -> &'a ShaderClosure;
}