♻️ refactor
parent
7f15b34591
commit
a6c4ebff39
|
@ -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
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
|
|
|
@ -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 ()
|
||||||
|
}
|
||||||
|
|
|
@ -87,3 +87,7 @@ impl ShaderClosure {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait ShaderLookup {
|
||||||
|
fn lookup <'a> (&'a self, id: u32) -> &'a ShaderClosure;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue