Start to rig stuff for the aerodynamics test I wanted to make in the first place
parent
afb0238c1b
commit
8a6d5518f1
|
@ -32,6 +32,7 @@ where V: Into <Vec3>
|
|||
))
|
||||
}
|
||||
|
||||
// TODO: Use iota macro
|
||||
const KEY_LEFT: usize = 0;
|
||||
const KEY_RIGHT: usize = KEY_LEFT + 1;
|
||||
const KEY_UP: usize = KEY_RIGHT + 1;
|
||||
|
@ -60,41 +61,79 @@ impl ControllerState {
|
|||
}
|
||||
}
|
||||
|
||||
struct EulerAngles {
|
||||
pub azimuth: f32,
|
||||
pub altitude: f32,
|
||||
}
|
||||
|
||||
impl Default for EulerAngles {
|
||||
fn default () -> Self {
|
||||
Self {
|
||||
azimuth: 0.0,
|
||||
altitude: 0.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl EulerAngles {
|
||||
pub fn to_vec3 (&self) -> Vec3 {
|
||||
let alt = self.altitude * std::f32::consts::PI / 180.0;
|
||||
let azi = self.azimuth * std::f32::consts::PI / 180.0;
|
||||
|
||||
let z = alt.sin ();
|
||||
let xy_len = alt.cos ();
|
||||
|
||||
let x = xy_len * azi.sin ();
|
||||
let y = xy_len * azi.cos ();
|
||||
|
||||
(x, y, z).into ()
|
||||
}
|
||||
}
|
||||
|
||||
struct WorldState {
|
||||
azimuth: f32,
|
||||
altitude: f32,
|
||||
camera: EulerAngles,
|
||||
wind: EulerAngles,
|
||||
spin_speed: i32,
|
||||
}
|
||||
|
||||
impl WorldState {
|
||||
pub fn new () -> Self {
|
||||
Self {
|
||||
azimuth: 0.0,
|
||||
altitude: 0.0,
|
||||
camera: Default::default (),
|
||||
wind: Default::default (),
|
||||
spin_speed: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn step (&mut self, controller: &ControllerState) {
|
||||
pub fn step (
|
||||
&mut self,
|
||||
controller: &ControllerState,
|
||||
user_control: &UserControl
|
||||
) {
|
||||
const SPIN_RAMP_TIME: i32 = 30;
|
||||
|
||||
let spin_f = 4.0 * self.spin_speed as f32 / SPIN_RAMP_TIME as f32;
|
||||
|
||||
let controlled_angle = match user_control {
|
||||
UserControl::Camera => &mut self.camera,
|
||||
UserControl::Wind => &mut self.wind,
|
||||
};
|
||||
|
||||
if controller.is_pressed (KEY_LEFT) {
|
||||
self.spin_speed = std::cmp::min (self.spin_speed + 1, SPIN_RAMP_TIME);
|
||||
self.azimuth += spin_f;
|
||||
controlled_angle.azimuth += spin_f;
|
||||
}
|
||||
else if controller.is_pressed (KEY_RIGHT) {
|
||||
self.spin_speed = std::cmp::min (self.spin_speed + 1, SPIN_RAMP_TIME);
|
||||
self.azimuth -= spin_f;
|
||||
controlled_angle.azimuth -= spin_f;
|
||||
}
|
||||
else if controller.is_pressed (KEY_UP) {
|
||||
self.spin_speed = std::cmp::min (self.spin_speed + 1, SPIN_RAMP_TIME);
|
||||
self.altitude = f32::min (90.0, self.altitude + spin_f);
|
||||
controlled_angle.altitude = f32::min (90.0, controlled_angle.altitude + spin_f);
|
||||
}
|
||||
else if controller.is_pressed (KEY_DOWN) {
|
||||
self.spin_speed = std::cmp::min (self.spin_speed + 1, SPIN_RAMP_TIME);
|
||||
self.altitude = f32::max (-90.0, self.altitude - spin_f);
|
||||
controlled_angle.altitude = f32::max (-90.0, controlled_angle.altitude - spin_f);
|
||||
}
|
||||
else {
|
||||
self.spin_speed = 0;
|
||||
|
@ -145,11 +184,13 @@ where P: AsRef <std::path::Path>
|
|||
struct Arrow {
|
||||
origin: Vec3,
|
||||
direction: Vec3,
|
||||
color: Vec3,
|
||||
}
|
||||
|
||||
struct RenderableArrow {
|
||||
model_mat: Mat4,
|
||||
inv_model_mat: Mat4,
|
||||
color: Vec3,
|
||||
}
|
||||
|
||||
#[derive (Copy, Clone, PartialEq, Eq)]
|
||||
|
@ -233,6 +274,37 @@ impl From <StencilFunc> for u32 {
|
|||
}
|
||||
}
|
||||
|
||||
#[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,
|
||||
|
@ -257,9 +329,12 @@ pub struct StencilState {
|
|||
// 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>,
|
||||
|
@ -269,9 +344,11 @@ pub struct IsoGlState {
|
|||
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,
|
||||
|
@ -282,13 +359,11 @@ impl std::default::Default for IsoGlState {
|
|||
// 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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -307,17 +382,13 @@ impl std::default::Default for GlState {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct Pass <'a> {
|
||||
pub struct Pass {
|
||||
// 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>,
|
||||
}
|
||||
|
||||
impl Pass <'_> {
|
||||
impl Pass {
|
||||
pub fn apply_diff (&self, old_state: &mut IsoGlState) {
|
||||
let state = &self.iso;
|
||||
|
||||
|
@ -381,6 +452,16 @@ impl Pass <'_> {
|
|||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
@ -425,15 +506,20 @@ impl Pass <'_> {
|
|||
callback ();
|
||||
}
|
||||
|
||||
pub fn with_shader <F> (&self, gl_state: &mut GlState, callback: F)
|
||||
where F: Fn (BorrowedShaderVars)
|
||||
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.shader {
|
||||
if let Some (s) = self.iso.shader_id {
|
||||
self.apply_diff (&mut gl_state.iso);
|
||||
s.with (gl_state.non_iso.shader_id, |shader_vars| {
|
||||
shader_component.lookup (s).with (gl_state.iso.shader_id, |shader_vars| {
|
||||
callback (shader_vars);
|
||||
});
|
||||
gl_state.non_iso.shader_id = Some (s.get_id ());
|
||||
gl_state.iso.shader_id = Some (s);
|
||||
}
|
||||
else {
|
||||
panic! ("Called with_shader on a pass with no shader");
|
||||
|
@ -441,9 +527,15 @@ impl Pass <'_> {
|
|||
}
|
||||
}
|
||||
|
||||
pub trait ShaderLookup {
|
||||
fn lookup <'a> (&'a self, id: u32) -> &'a ShaderClosure;
|
||||
}
|
||||
|
||||
struct GameGraphics {
|
||||
shader_diffuse: ShaderClosure,
|
||||
shader_shadow: ShaderClosure,
|
||||
passes: Vec <Pass>,
|
||||
|
||||
shaders: Vec <ShaderClosure>,
|
||||
shader_lookup: HashMap <u32, usize>,
|
||||
|
||||
mesh_pumpkin: RenderableModel,
|
||||
mesh_sky: RenderableModel,
|
||||
|
@ -456,6 +548,12 @@ struct GameGraphics {
|
|||
grass_index: usize,
|
||||
}
|
||||
|
||||
impl ShaderLookup for GameGraphics {
|
||||
fn lookup <'a> (&'a self, id: u32) -> &'a ShaderClosure {
|
||||
&self.shaders [self.shader_lookup [&id]]
|
||||
}
|
||||
}
|
||||
|
||||
impl GameGraphics {
|
||||
pub fn new () -> Self {
|
||||
let uniform_names = {
|
||||
|
@ -480,10 +578,21 @@ impl GameGraphics {
|
|||
]
|
||||
};
|
||||
|
||||
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 shaders: Vec <_> = [
|
||||
("shaders/pumpkin-vert.glsl", "shaders/pumpkin-frag.glsl"),
|
||||
("shaders/shadow-vert.glsl", "shaders/shadow-frag.glsl"),
|
||||
].iter ()
|
||||
.map (|(v, f)| {
|
||||
ShaderClosure::new (shader_from_files (v, f), &uniform_names, &attr_names)
|
||||
})
|
||||
.collect ();
|
||||
|
||||
shader_diffuse.with (None, |shader_vars| {
|
||||
let shader_lookup = HashMap::from_iter (shaders.iter ().enumerate ()
|
||||
.map (|(i, s)| {
|
||||
(s.get_id (), i)
|
||||
}));
|
||||
|
||||
shaders [0].with (None, |shader_vars| {
|
||||
let attrs = shader_vars.attrs;
|
||||
use renderable_model::attributes::*;
|
||||
glezz::enable_vertex_attrib_array (attrs [POS]);
|
||||
|
@ -538,9 +647,183 @@ impl GameGraphics {
|
|||
(colors, grass_index.unwrap ())
|
||||
};
|
||||
|
||||
let passes = vec! [
|
||||
// Clear everything
|
||||
Pass {
|
||||
iso: IsoGlState {
|
||||
shader_id: None,
|
||||
flags: hashmap! {},
|
||||
front_face: None,
|
||||
stencil: None,
|
||||
depth_func: None,
|
||||
color_mask: Some ((1, 1, 1, 1)),
|
||||
depth_mask: Some (1),
|
||||
stencil_mask: Some (255),
|
||||
},
|
||||
},
|
||||
// Draw world
|
||||
Pass {
|
||||
iso: IsoGlState {
|
||||
shader_id: Some (shaders [0].get_id ()),
|
||||
flags: hashmap! {
|
||||
gl::CULL_FACE => true,
|
||||
gl::DEPTH_TEST => true,
|
||||
gl::TEXTURE_2D => true,
|
||||
gl::STENCIL_TEST => false,
|
||||
},
|
||||
front_face: Some (FrontFace::Cw),
|
||||
stencil: Some (StencilState {
|
||||
func: StencilFuncState {
|
||||
func: StencilFunc::Always,
|
||||
reference: 0,
|
||||
mask: 0,
|
||||
},
|
||||
op: StencilOpState {
|
||||
sfail: StencilOp::Keep,
|
||||
dpfail: StencilOp::Keep,
|
||||
dppass: StencilOp::Keep,
|
||||
},
|
||||
}),
|
||||
depth_func: Some (DepthFunc::Less),
|
||||
color_mask: Some ((1, 1, 1, 1)),
|
||||
depth_mask: Some (1),
|
||||
stencil_mask: Some (0),
|
||||
},
|
||||
},
|
||||
// Write shadows into stencil buffer
|
||||
Pass {
|
||||
iso: IsoGlState {
|
||||
shader_id: Some (shaders [1].get_id ()),
|
||||
flags: hashmap! {
|
||||
gl::CULL_FACE => true,
|
||||
gl::DEPTH_TEST => true,
|
||||
gl::STENCIL_TEST => true,
|
||||
},
|
||||
front_face: Some (FrontFace::Ccw),
|
||||
stencil: Some (StencilState {
|
||||
func: StencilFuncState {
|
||||
func: StencilFunc::Always,
|
||||
reference: 1,
|
||||
mask: 1,
|
||||
},
|
||||
op: StencilOpState {
|
||||
sfail: StencilOp::Keep,
|
||||
dpfail: StencilOp::Keep,
|
||||
dppass: StencilOp::Replace,
|
||||
},
|
||||
}),
|
||||
depth_func: Some (DepthFunc::Less),
|
||||
color_mask: Some ((0, 0, 0, 0)),
|
||||
depth_mask: Some (0),
|
||||
stencil_mask: Some (255),
|
||||
},
|
||||
},
|
||||
// Draw lit ground
|
||||
Pass {
|
||||
iso: IsoGlState {
|
||||
shader_id: Some (shaders [0].get_id ()),
|
||||
flags: hashmap! {
|
||||
gl::CULL_FACE => true,
|
||||
gl::DEPTH_TEST => true,
|
||||
gl::TEXTURE_2D => true,
|
||||
gl::STENCIL_TEST => true,
|
||||
},
|
||||
front_face: Some (FrontFace::Cw),
|
||||
stencil: Some (StencilState {
|
||||
func: StencilFuncState {
|
||||
func: StencilFunc::NotEqual,
|
||||
reference: 0,
|
||||
mask: 1,
|
||||
},
|
||||
op: StencilOpState {
|
||||
sfail: StencilOp::Keep,
|
||||
dpfail: StencilOp::Keep,
|
||||
dppass: StencilOp::Keep,
|
||||
},
|
||||
}),
|
||||
depth_func: Some (DepthFunc::Less),
|
||||
color_mask: Some ((1, 1, 1, 1)),
|
||||
depth_mask: Some (1),
|
||||
stencil_mask: Some (0),
|
||||
},
|
||||
},
|
||||
// Draw unlit ground
|
||||
Pass {
|
||||
iso: IsoGlState {
|
||||
shader_id: Some (shaders [0].get_id ()),
|
||||
flags: hashmap! {
|
||||
gl::CULL_FACE => true,
|
||||
gl::DEPTH_TEST => true,
|
||||
gl::TEXTURE_2D => true,
|
||||
gl::STENCIL_TEST => true,
|
||||
},
|
||||
front_face: Some (FrontFace::Cw),
|
||||
stencil: Some (StencilState {
|
||||
func: StencilFuncState {
|
||||
func: StencilFunc::Equal,
|
||||
reference: 0,
|
||||
mask: 1,
|
||||
},
|
||||
op: StencilOpState {
|
||||
sfail: StencilOp::Keep,
|
||||
dpfail: StencilOp::Keep,
|
||||
dppass: StencilOp::Keep,
|
||||
},
|
||||
}),
|
||||
depth_func: Some (DepthFunc::Less),
|
||||
color_mask: Some ((1, 1, 1, 1)),
|
||||
depth_mask: Some (1),
|
||||
stencil_mask: Some (0),
|
||||
},
|
||||
},
|
||||
// Clear depth
|
||||
Pass {
|
||||
iso: IsoGlState {
|
||||
shader_id: None,
|
||||
flags: hashmap! {},
|
||||
front_face: None,
|
||||
stencil: None,
|
||||
depth_func: None,
|
||||
color_mask: None,
|
||||
depth_mask: Some (1),
|
||||
stencil_mask: None,
|
||||
},
|
||||
},
|
||||
// Draw arrows
|
||||
Pass {
|
||||
iso: IsoGlState {
|
||||
shader_id: Some (shaders [0].get_id ()),
|
||||
flags: hashmap! {
|
||||
gl::CULL_FACE => true,
|
||||
gl::DEPTH_TEST => true,
|
||||
gl::TEXTURE_2D => true,
|
||||
gl::STENCIL_TEST => false,
|
||||
},
|
||||
front_face: Some (FrontFace::Cw),
|
||||
stencil: Some (StencilState {
|
||||
func: StencilFuncState {
|
||||
func: StencilFunc::Always,
|
||||
reference: 0,
|
||||
mask: 0,
|
||||
},
|
||||
op: StencilOpState {
|
||||
sfail: StencilOp::Keep,
|
||||
dpfail: StencilOp::Keep,
|
||||
dppass: StencilOp::Keep,
|
||||
},
|
||||
}),
|
||||
depth_func: Some (DepthFunc::Less),
|
||||
color_mask: Some ((1, 1, 1, 1)),
|
||||
depth_mask: Some (1),
|
||||
stencil_mask: Some (0),
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
Self {
|
||||
shader_diffuse,
|
||||
shader_shadow,
|
||||
passes,
|
||||
shaders,
|
||||
shader_lookup,
|
||||
|
||||
mesh_pumpkin,
|
||||
mesh_sky,
|
||||
|
@ -574,8 +857,8 @@ impl GameGraphics {
|
|||
green,
|
||||
];
|
||||
|
||||
let longitude = state.azimuth.to_radians ();
|
||||
let latitude = (state.altitude - 90.0).to_radians ();
|
||||
let longitude = state.camera.azimuth.to_radians ();
|
||||
let latitude = (state.camera.altitude - 90.0).to_radians ();
|
||||
|
||||
let proj_mat = Mat4::perspective_rh_gl (30.0f32.to_radians (), 1280.0 / 720.0, 0.5, 500.0);
|
||||
|
||||
|
@ -598,122 +881,9 @@ impl GameGraphics {
|
|||
|
||||
//println! ("Started frame");
|
||||
|
||||
let passes = vec! [
|
||||
// Clear everything
|
||||
Pass {
|
||||
shader: None,
|
||||
iso: IsoGlState {
|
||||
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),
|
||||
iso: IsoGlState {
|
||||
flags: hashmap! {
|
||||
gl::CULL_FACE => true,
|
||||
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: Some (&self.shader_shadow),
|
||||
iso: IsoGlState {
|
||||
flags: hashmap! {
|
||||
gl::CULL_FACE => true,
|
||||
gl::DEPTH_TEST => true,
|
||||
gl::STENCIL_TEST => true,
|
||||
},
|
||||
front_face: Some (FrontFace::Ccw),
|
||||
stencil: Some (StencilState {
|
||||
func: StencilFuncState {
|
||||
func: StencilFunc::Always,
|
||||
reference: 1,
|
||||
mask: 1,
|
||||
},
|
||||
op: StencilOpState {
|
||||
sfail: StencilOp::Keep,
|
||||
dpfail: StencilOp::Keep,
|
||||
dppass: StencilOp::Replace,
|
||||
},
|
||||
}),
|
||||
color_mask: Some ((0, 0, 0, 0)),
|
||||
depth_mask: Some (0),
|
||||
stencil_mask: Some (255),
|
||||
},
|
||||
},
|
||||
// Draw lit ground
|
||||
Pass {
|
||||
shader: Some (&self.shader_diffuse),
|
||||
iso: IsoGlState {
|
||||
flags: hashmap! {
|
||||
gl::CULL_FACE => true,
|
||||
gl::DEPTH_TEST => true,
|
||||
gl::TEXTURE_2D => true,
|
||||
gl::STENCIL_TEST => true,
|
||||
},
|
||||
front_face: Some (FrontFace::Cw),
|
||||
stencil: Some (StencilState {
|
||||
func: StencilFuncState {
|
||||
func: StencilFunc::NotEqual,
|
||||
reference: 0,
|
||||
mask: 1,
|
||||
},
|
||||
op: StencilOpState {
|
||||
sfail: StencilOp::Keep,
|
||||
dpfail: StencilOp::Keep,
|
||||
dppass: StencilOp::Keep,
|
||||
},
|
||||
}),
|
||||
color_mask: Some ((1, 1, 1, 1)),
|
||||
depth_mask: Some (1),
|
||||
stencil_mask: Some (0),
|
||||
},
|
||||
},
|
||||
// Draw unlit ground
|
||||
Pass {
|
||||
shader: Some (&self.shader_diffuse),
|
||||
iso: IsoGlState {
|
||||
flags: hashmap! {
|
||||
gl::CULL_FACE => true,
|
||||
gl::DEPTH_TEST => true,
|
||||
gl::TEXTURE_2D => true,
|
||||
gl::STENCIL_TEST => true,
|
||||
},
|
||||
front_face: Some (FrontFace::Cw),
|
||||
stencil: Some (StencilState {
|
||||
func: StencilFuncState {
|
||||
func: StencilFunc::Equal,
|
||||
reference: 0,
|
||||
mask: 1,
|
||||
},
|
||||
op: StencilOpState {
|
||||
sfail: StencilOp::Keep,
|
||||
dpfail: StencilOp::Keep,
|
||||
dppass: StencilOp::Keep,
|
||||
},
|
||||
}),
|
||||
color_mask: Some ((1, 1, 1, 1)),
|
||||
depth_mask: Some (1),
|
||||
stencil_mask: Some (0),
|
||||
},
|
||||
},
|
||||
];
|
||||
let mut passes = self.passes.iter ();
|
||||
|
||||
passes [0].with (gl_state, || {
|
||||
passes.next ().unwrap ().with (gl_state, || {
|
||||
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);
|
||||
});
|
||||
|
@ -730,7 +900,8 @@ impl GameGraphics {
|
|||
use uniforms::*;
|
||||
|
||||
// Draw the world except the ground plane
|
||||
passes [1].with_shader (gl_state, |shader_vars| {
|
||||
passes.next ().unwrap ().with_shader (gl_state, self,
|
||||
|shader_vars| {
|
||||
let unis = shader_vars.unis;
|
||||
let attrs = shader_vars.attrs;
|
||||
|
||||
|
@ -759,19 +930,6 @@ impl GameGraphics {
|
|||
i != self.grass_index
|
||||
});
|
||||
|
||||
glezz::uniform_3fv (unis [&ALBEDO], &magenta);
|
||||
for arrow in arrows.iter () {
|
||||
let mvp = view_mat * arrow.model_mat;
|
||||
|
||||
glezz::uniform_matrix_4fv (unis [&MVP], &mvp);
|
||||
let object_space_light = make_object_space_vec (&arrow.inv_model_mat, &light);
|
||||
let object_space_sky = make_object_space_vec (&arrow.inv_model_mat, &Vec3::from ((0.0, 0.0, 1.0)));
|
||||
glezz::uniform_3fv (unis [&OBJECT_SPACE_LIGHT], &object_space_light);
|
||||
glezz::uniform_3fv (unis [&OBJECT_SPACE_SKY], &object_space_sky);
|
||||
|
||||
self.mesh_arrow.draw_all (attrs, |_| true);
|
||||
}
|
||||
|
||||
let draw_sky = true;
|
||||
if draw_sky {
|
||||
self.texture.bind ();
|
||||
|
@ -786,7 +944,8 @@ impl GameGraphics {
|
|||
});
|
||||
|
||||
// Draw shadows into stencil buffer
|
||||
passes [2].with_shader (gl_state, |shader_vars| {
|
||||
passes.next ().unwrap ().with_shader (gl_state, self,
|
||||
|shader_vars| {
|
||||
let unis = shader_vars.unis;
|
||||
let attrs = shader_vars.attrs;
|
||||
|
||||
|
@ -813,7 +972,8 @@ impl GameGraphics {
|
|||
let object_space_light = make_object_space_vec (&inverse_pumpkin, &light);
|
||||
|
||||
// Draw unlit ground
|
||||
passes [3].with_shader (gl_state, |shader_vars| {
|
||||
passes.next ().unwrap ().with_shader (gl_state, self,
|
||||
|shader_vars| {
|
||||
let unis = shader_vars.unis;
|
||||
let attrs = shader_vars.attrs;
|
||||
|
||||
|
@ -835,14 +995,49 @@ impl GameGraphics {
|
|||
});
|
||||
|
||||
// Draw lit ground
|
||||
passes [4].with_shader (gl_state, |shader_vars| {
|
||||
passes.next ().unwrap ().with_shader (gl_state, self,
|
||||
|shader_vars| {
|
||||
let unis = shader_vars.unis;
|
||||
let attrs = shader_vars.attrs;
|
||||
|
||||
glezz::uniform_3fv (unis [&OBJECT_SPACE_LIGHT], &object_space_light);
|
||||
self.mesh_pitch.draw (attrs, self.grass_index);
|
||||
});
|
||||
|
||||
// Clear depth
|
||||
passes.next ().unwrap ().with (gl_state, || {
|
||||
glezz::clear (gl::DEPTH_BUFFER_BIT);
|
||||
});
|
||||
|
||||
// Draw arrows
|
||||
passes.next ().unwrap ().with_shader (gl_state, self,
|
||||
|shader_vars| {
|
||||
let unis = &shader_vars.unis;
|
||||
|
||||
glezz::uniform_3fv (unis [&MIN_BRIGHT], &black);
|
||||
glezz::uniform_3fv (unis [&MIN_ALBEDO], &white);
|
||||
|
||||
for arrow in arrows.iter () {
|
||||
let mvp = view_mat * arrow.model_mat;
|
||||
|
||||
glezz::uniform_matrix_4fv (unis [&MVP], &mvp);
|
||||
let object_space_light = make_object_space_vec (&arrow.inv_model_mat, &light);
|
||||
let object_space_sky = make_object_space_vec (&arrow.inv_model_mat, &Vec3::from ((0.0, 0.0, 1.0)));
|
||||
glezz::uniform_3fv (unis [&OBJECT_SPACE_LIGHT], &object_space_light);
|
||||
glezz::uniform_3fv (unis [&OBJECT_SPACE_SKY], &object_space_sky);
|
||||
|
||||
glezz::uniform_3fv (unis [&ALBEDO], &arrow.color);
|
||||
|
||||
self.mesh_arrow.draw_all (shader_vars.attrs, |_| true);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[derive (Copy, Clone, PartialEq, Eq)]
|
||||
enum UserControl {
|
||||
Camera,
|
||||
Wind,
|
||||
}
|
||||
|
||||
fn main () {
|
||||
|
@ -871,16 +1066,13 @@ fn main () {
|
|||
let graphics = GameGraphics::new ();
|
||||
let mut gl_state = Default::default ();
|
||||
|
||||
let mut user_control = UserControl::Camera;
|
||||
let mut graphics_frames = 0;
|
||||
|
||||
let mut event_pump = sdl_context.event_pump ().unwrap ();
|
||||
'running: loop {
|
||||
let frames_to_do = time_step.step ();
|
||||
|
||||
let controller = ControllerState::from_sdl_keyboard (&event_pump.keyboard_state ());
|
||||
|
||||
for _ in 0..frames_to_do {
|
||||
state.step (&controller);
|
||||
}
|
||||
|
||||
let _mouse = event_pump.mouse_state ();
|
||||
|
||||
for event in event_pump.poll_iter() {
|
||||
|
@ -889,27 +1081,55 @@ fn main () {
|
|||
Event::KeyDown { keycode: Some (Keycode::Escape), .. } => {
|
||||
break 'running
|
||||
},
|
||||
Event::KeyDown { keycode: Some (Keycode::C), .. } => {
|
||||
user_control = UserControl::Camera;
|
||||
},
|
||||
Event::KeyDown { keycode: Some (Keycode::W), .. } => {
|
||||
user_control = UserControl::Wind;
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
let controller = ControllerState::from_sdl_keyboard (&event_pump.keyboard_state ());
|
||||
|
||||
for _ in 0..frames_to_do {
|
||||
state.step (&controller, &user_control);
|
||||
}
|
||||
|
||||
let gravity = (0.0, 0.0, -1.0).into ();
|
||||
let wind = state.wind.to_vec3 () * -1.0;
|
||||
let origin: Vec3 = (0.0, 0.0, 1.35).into ();
|
||||
|
||||
let control_flash = if graphics_frames % 16 >= 8 {
|
||||
(1.0, 1.0, 1.0).into ()
|
||||
}
|
||||
else {
|
||||
(1.0, 0.0, 0.0).into ()
|
||||
};
|
||||
|
||||
let arrows = vec![
|
||||
Arrow {
|
||||
origin: (0.0, 0.0, 1.0).into (),
|
||||
direction: (0.0, 0.0, 1.0).into (),
|
||||
origin: (0.0, 0.0, 1.35).into (),
|
||||
direction: gravity,
|
||||
color: (1.0, 0.5, 0.5).into (),
|
||||
},
|
||||
Arrow {
|
||||
origin: (1.0, 0.0, 1.0).into (),
|
||||
direction: (1.0, 0.0, 0.0).into (),
|
||||
origin: origin + wind * -2.0,
|
||||
direction: wind,
|
||||
color: if user_control == UserControl::Wind {
|
||||
control_flash
|
||||
}
|
||||
else {
|
||||
(1.0, 0.5, 1.0).into ()
|
||||
},
|
||||
Arrow {
|
||||
origin: (0.0, 1.0, 1.0).into (),
|
||||
direction: (0.0, 1.0, 0.0).into (),
|
||||
},
|
||||
];
|
||||
|
||||
let renderable_arrows: Vec <_> = arrows.iter ().map (|arrow| {
|
||||
let d = arrow.direction;
|
||||
let dir_len = arrow.direction.length ();
|
||||
|
||||
let d = arrow.direction / dir_len;
|
||||
|
||||
let up: Vec3 = if d.z () > 0.5 {
|
||||
(-1.0, 0.0, 0.0)
|
||||
|
@ -932,9 +1152,11 @@ fn main () {
|
|||
dir_mat.set_y_axis ((up.x (), up.y (), up.z (), 0.0).into ());
|
||||
dir_mat.set_z_axis ((d.x (), d.y (), d.z (), 0.0).into ());
|
||||
|
||||
let s = dir_len * 0.0625;
|
||||
|
||||
let model_mat =
|
||||
Mat4::from_translation (arrow.origin) *
|
||||
Mat4::from_scale ((0.125, 0.125, 0.125).into ()) *
|
||||
Mat4::from_scale ((s, s, s).into ()) *
|
||||
dir_mat;
|
||||
|
||||
let inv_model_mat = model_mat.inverse ();
|
||||
|
@ -942,6 +1164,7 @@ fn main () {
|
|||
RenderableArrow {
|
||||
model_mat,
|
||||
inv_model_mat,
|
||||
color: arrow.color,
|
||||
}
|
||||
}).collect ();
|
||||
|
||||
|
@ -950,6 +1173,7 @@ fn main () {
|
|||
graphics.draw (&state, &mut gl_state, &renderable_arrows);
|
||||
|
||||
window.gl_swap_window ();
|
||||
graphics_frames += 1;
|
||||
|
||||
std::thread::sleep (Duration::from_millis (15));
|
||||
}
|
||||
|
|
|
@ -97,6 +97,12 @@ pub fn stencil_mask (v: u32) {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn depth_func (v: u32) {
|
||||
unsafe {
|
||||
gl::DepthFunc (v);
|
||||
}
|
||||
}
|
||||
|
||||
// More abstract things below here
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue