From d9534554d1d7dacd53af65996467db12f8cc8136 Mon Sep 17 00:00:00 2001 From: _ <_@_> Date: Sun, 19 Dec 2021 16:44:01 +0000 Subject: [PATCH] :recycle: refactor --- src/bin/platformer/graphics.rs | 303 +++++++++++++++++++++++++++++++++ src/bin/platformer/main.rs | 283 +----------------------------- 2 files changed, 308 insertions(+), 278 deletions(-) create mode 100644 src/bin/platformer/graphics.rs diff --git a/src/bin/platformer/graphics.rs b/src/bin/platformer/graphics.rs new file mode 100644 index 0000000..a0187ab --- /dev/null +++ b/src/bin/platformer/graphics.rs @@ -0,0 +1,303 @@ +use std::{ + collections::HashMap, +}; + +use opengl_rust::{ + prelude::*, + gl_state::{ + FrontFace, + GlState, + Pass, + }, + renderable_model::{ + attributes, + RenderableModel, + }, + shader_closure::ShaderLookup, + texture::Texture, +}; + +use crate::{ + GameState, + TriangleStream, +}; + +mod uniforms { +use iota::iota; +iota! { +pub const + MVP: u32 = iota; + , OBJECT_SPACE_LIGHT + , OBJECT_SPACE_SKY + , ALBEDO + , MIN_ALBEDO + , MIN_BRIGHT + , TEXTURE +} +} + +pub struct Graphics { + passes: Vec , + + shaders: Vec , + shader_lookup: HashMap , + + mesh_cube: RenderableModel, + mesh_sky: RenderableModel, + mesh_sphere: RenderableModel, + + text_stream: TriangleStream, + + texture_crate: Texture, + texture_earth: Texture, + texture_sky: Texture, + + pub frames: u64, +} + +impl ShaderLookup for Graphics { + fn lookup <'a> (&'a self, id: u32) -> &'a ShaderClosure { + &self.shaders [self.shader_lookup [&id]] + } +} + +impl Graphics { + pub fn new () -> Self { + let uniform_names = { + vec! [ + (uniforms::MVP, "uni_mvp"), + (uniforms::OBJECT_SPACE_LIGHT, "uni_object_space_light"), + (uniforms::OBJECT_SPACE_SKY, "uni_object_space_sky"), + (uniforms::ALBEDO, "uni_albedo"), + (uniforms::MIN_ALBEDO, "uni_min_albedo"), + (uniforms::MIN_BRIGHT, "uni_min_bright"), + (uniforms::TEXTURE, "uni_texture"), + ] + }; + + let attr_names = { + vec! [ + (attributes::POS, "attr_pos"), + (attributes::UV, "attr_uv"), + (attributes::NORMAL, "attr_normal"), + ] + }; + + let shaders: Vec <_> = [ + ("shaders/pumpkin-vert.glsl", "shaders/pumpkin-frag.glsl"), + ("shaders/shadow-vert.glsl", "shaders/shadow-frag.glsl"), + ("shaders/terrain-vert.glsl", "shaders/terrain-frag.glsl"), + ].into_iter () + .map (|(v, f)| { + ShaderClosure::new (shader_from_files (v, f), &uniform_names, &attr_names) + }) + .collect (); + + let mesh_cube = renderable_from_iqm_file ("cube.iqm"); + let mesh_sky = renderable_from_iqm_file ("sky-sphere.iqm"); + let mesh_sphere = renderable_from_iqm_file ("sphere.iqm"); + + let passes = vec![ + // Clear everything + Pass::default () + .color_mask ([1, 1, 1, 1]) + .depth_mask (1) + .clone (), + // Draw world + Pass::default () + .shader (&shaders [0]) + .flags ([ + (gl::CULL_FACE, true), + (gl::DEPTH_TEST, true), + (gl::TEXTURE_2D, true), + (gl::STENCIL_TEST, false), + ].into_iter ()) + .front_face (FrontFace::Ccw) + .color_mask ([1, 1, 1, 1]) + .depth_mask (1) + .clone (), + ]; + + let text_stream = TriangleStream { + verts: gpu_buffers::VertexBuffer::streaming (4 * 5 * 6 * 1024), + indices: { + let quad = [ + 0, 1, 2, + 0, 2, 3, + ]; + + let v: Vec = (0u32..1024).map (|i| { + quad.iter ().map (move |j| 4 * i + j) + }).flatten ().collect (); + gpu_buffers::IndexBuffer::from_slice_u32 (&v) + } + }; + + 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; + glezz::enable_vertex_attrib_array (attrs [attributes::POS]); + glezz::enable_vertex_attrib_array (attrs [attributes::UV]); + glezz::enable_vertex_attrib_array (attrs [attributes::NORMAL]); + }); + + Graphics { + mesh_cube, + mesh_sky, + mesh_sphere, + passes, + shader_lookup, + shaders, + text_stream, + texture_crate: Texture::from_file ("crate.png"), + texture_earth: Texture::from_file ("earth.png"), + texture_sky: Texture::from_file ("sky.png"), + frames: 0, + } + } + + pub fn draw ( + &self, + state: &GameState, + gl_state: &mut GlState, + ) { + use uniforms as u; + + let white = color_from_255 ((255.0, 255.0, 255.0)); + let black = color_from_255 ((0.0, 0.0, 0.0)); + let shadow_blue = color_from_255 ((0.0, 0.0, 0.25)); + + let screen_size = (320.0, 240.0); + + let fov = 30.0f32; + + let proj_mat = Mat4::perspective_rh_gl (fov.to_radians (), screen_size.0 / screen_size.1, 0.125, 200.0); + + let view_mat = proj_mat * + Mat4::from_translation ((0.0, 0.0, -20.0).into ()) * + Mat4::from_rotation_x ((45.0 - 90.0f32).to_radians ()) + ; + let world_model_mat = Mat4::IDENTITY; + + self.passes [0].with (gl_state, || { + glezz::clear_color (0.5f32, 0.5f32, 0.5f32, 1.0f32); + glezz::clear (gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT | gl::STENCIL_BUFFER_BIT); + }); + + self.passes [1].with_shader (gl_state, self, |shader_vars| { + let attrs = shader_vars.attrs; + let unis = shader_vars.unis; + + self.texture_earth.bind (); + + { + let mvp = view_mat * + Mat4::from_translation (state.player.pos) * + Mat4::from_scale ((0.5, 0.5, 0.5).into ()); + glezz::uniform_matrix_4fv (unis [&u::MVP], &mvp); + glezz::uniform_3fv (unis [&u::ALBEDO], &white); + + self.mesh_sphere.draw_all (attrs, |_| { + true + }); + } + + self.texture_crate.bind (); + glezz::uniform_3fv (unis [&u::ALBEDO], &white); + + for aabb in &state.aabbs { + let min = aabb.min; + let max = aabb.max; + let center = (min + max) / 2.0; + let scale = (max - min) / 2.0; + + let mvp = view_mat * + Mat4::from_translation (center) * + Mat4::from_scale (scale); + glezz::uniform_matrix_4fv (unis [&u::MVP], &mvp); + + self.mesh_cube.draw_all (attrs, |_| { + true + }); + } + + glezz::uniform_3fv (unis [&u::ALBEDO], &shadow_blue); + + if true { + // Raycast for player shadow + let coll = opengl_rust::physics::get_candidate ( + &[], &state.aabbs, + state.player.pos, + state.player.pos + Vec3::new (0.0, 0.0, -100.0), + 0.0 + ); + + if coll.t <= 1.0 { + let mvp = view_mat * + Mat4::from_translation (coll.p_impact + Vec3::new (0.0, 0.0, 0.0625)) * + Mat4::from_scale ((0.5, 0.5, 0.0).into ()); + glezz::uniform_matrix_4fv (unis [&u::MVP], &mvp); + + self.mesh_sphere.draw_all (attrs, |_| { + true + }); + } + + for aabb in &state.aabbs { + // Raycast for box shadows + let min = aabb.min; + let max = aabb.max; + let center = (min + max) / 2.0; + let scale = (max - min) / 2.0; + + let coll = opengl_rust::physics::get_candidate ( + &[], &state.aabbs, + center, + center + Vec3::new (0.0, 0.0, -100.0), + 0.0 + ); + + if coll.t <= 1.0 { + let mvp = view_mat * + Mat4::from_translation (coll.p_impact + Vec3::new (0.0, 0.0, 0.0625)) * + Mat4::from_scale ((scale.x, scale.y, 0.0).into ()); + glezz::uniform_matrix_4fv (unis [&u::MVP], &mvp); + + self.mesh_cube.draw_all (attrs, |_| { + true + }); + } + } + } + + { + let sky_mvp_mat = view_mat * Mat4::from_scale ((64.0, 64.0, 64.0).into ()); + + self.texture_sky.bind (); + glezz::uniform_matrix_4fv (unis [&u::MVP], &sky_mvp_mat); + glezz::uniform_3fv (unis [&u::ALBEDO], &white); + glezz::uniform_3fv (unis [&u::MIN_BRIGHT], &white); + glezz::uniform_3fv (unis [&u::MIN_ALBEDO], &black); + glezz::uniform_1i (unis [&u::TEXTURE], 0); + + // self.mesh_sky.draw_all (attrs, |_| true); + } + }); + } +} + +fn color_from_255 (rgb: V) -> Vec3 +where V: Into +{ + let rgb: Vec3 = rgb.into (); + + Vec3::from (( + rgb.x / 255.0, + rgb.y / 255.0, + rgb.z / 255.0 + )) +} diff --git a/src/bin/platformer/main.rs b/src/bin/platformer/main.rs index 2992f1f..f696861 100644 --- a/src/bin/platformer/main.rs +++ b/src/bin/platformer/main.rs @@ -17,21 +17,11 @@ use opengl_rust::{ texture::Texture, }; -mod uniforms { -use iota::iota; -iota! { -pub const - MVP: u32 = iota; - , OBJECT_SPACE_LIGHT - , OBJECT_SPACE_SKY - , ALBEDO - , MIN_ALBEDO - , MIN_BRIGHT - , TEXTURE -} -} +mod graphics; -struct GameState { +use graphics::Graphics; + +pub struct GameState { player: PhysicsBody, aabbs: Vec , } @@ -60,162 +50,6 @@ impl Default for GameState { } } -struct GameGraphics { - passes: Vec , - - shaders: Vec , - shader_lookup: HashMap , - - mesh_cube: RenderableModel, - mesh_sky: RenderableModel, - mesh_sphere: RenderableModel, - - text_stream: TriangleStream, - - texture_crate: Texture, - texture_earth: Texture, - texture_sky: Texture, - - frames: u64, -} - -impl ShaderLookup for GameGraphics { - fn lookup <'a> (&'a self, id: u32) -> &'a ShaderClosure { - &self.shaders [self.shader_lookup [&id]] - } -} - -impl GameGraphics { - fn draw ( - &self, - state: &GameState, - gl_state: &mut GlState, - ) { - use uniforms as u; - - let white = color_from_255 ((255.0, 255.0, 255.0)); - let black = color_from_255 ((0.0, 0.0, 0.0)); - let shadow_blue = color_from_255 ((0.0, 0.0, 0.25)); - - let screen_size = (320.0, 240.0); - - let fov = 30.0f32; - - let proj_mat = Mat4::perspective_rh_gl (fov.to_radians (), screen_size.0 / screen_size.1, 0.125, 200.0); - - let view_mat = proj_mat * - Mat4::from_translation ((0.0, 0.0, -20.0).into ()) * - Mat4::from_rotation_x ((45.0 - 90.0f32).to_radians ()) - ; - let world_model_mat = Mat4::IDENTITY; - - self.passes [0].with (gl_state, || { - glezz::clear_color (0.5f32, 0.5f32, 0.5f32, 1.0f32); - glezz::clear (gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT | gl::STENCIL_BUFFER_BIT); - }); - - self.passes [1].with_shader (gl_state, self, |shader_vars| { - let attrs = shader_vars.attrs; - let unis = shader_vars.unis; - - self.texture_earth.bind (); - - { - let mvp = view_mat * - Mat4::from_translation (state.player.pos) * - Mat4::from_scale ((0.5, 0.5, 0.5).into ()); - glezz::uniform_matrix_4fv (unis [&u::MVP], &mvp); - glezz::uniform_3fv (unis [&u::ALBEDO], &white); - - self.mesh_sphere.draw_all (attrs, |_| { - true - }); - } - - self.texture_crate.bind (); - glezz::uniform_3fv (unis [&u::ALBEDO], &white); - - for aabb in &state.aabbs { - let min = aabb.min; - let max = aabb.max; - let center = (min + max) / 2.0; - let scale = (max - min) / 2.0; - - let mvp = view_mat * - Mat4::from_translation (center) * - Mat4::from_scale (scale); - glezz::uniform_matrix_4fv (unis [&u::MVP], &mvp); - - self.mesh_cube.draw_all (attrs, |_| { - true - }); - } - - glezz::uniform_3fv (unis [&u::ALBEDO], &shadow_blue); - - if true { - // Raycast for player shadow - let coll = opengl_rust::physics::get_candidate ( - &[], &state.aabbs, - state.player.pos, - state.player.pos + Vec3::new (0.0, 0.0, -100.0), - 0.0 - ); - - if coll.t <= 1.0 { - let mvp = view_mat * - Mat4::from_translation (coll.p_impact + Vec3::new (0.0, 0.0, 0.0625)) * - Mat4::from_scale ((0.5, 0.5, 0.0).into ()); - glezz::uniform_matrix_4fv (unis [&u::MVP], &mvp); - - self.mesh_sphere.draw_all (attrs, |_| { - true - }); - } - - for aabb in &state.aabbs { - // Raycast for box shadows - let min = aabb.min; - let max = aabb.max; - let center = (min + max) / 2.0; - let scale = (max - min) / 2.0; - - let coll = opengl_rust::physics::get_candidate ( - &[], &state.aabbs, - center, - center + Vec3::new (0.0, 0.0, -100.0), - 0.0 - ); - - if coll.t <= 1.0 { - let mvp = view_mat * - Mat4::from_translation (coll.p_impact + Vec3::new (0.0, 0.0, 0.0625)) * - Mat4::from_scale ((scale.x, scale.y, 0.0).into ()); - glezz::uniform_matrix_4fv (unis [&u::MVP], &mvp); - - self.mesh_cube.draw_all (attrs, |_| { - true - }); - } - } - } - - { - let sky_mvp_mat = view_mat * Mat4::from_scale ((64.0, 64.0, 64.0).into ()); - - self.texture_sky.bind (); - glezz::uniform_matrix_4fv (unis [&u::MVP], &sky_mvp_mat); - glezz::uniform_3fv (unis [&u::ALBEDO], &white); - glezz::uniform_3fv (unis [&u::MIN_BRIGHT], &white); - glezz::uniform_3fv (unis [&u::MIN_ALBEDO], &black); - glezz::uniform_1i (unis [&u::TEXTURE], 0); - - // self.mesh_sky.draw_all (attrs, |_| true); - } - }); - } -} - #[tokio::main] async fn main () -> Result <()> { tracing_subscriber::fmt::fmt () @@ -246,41 +80,6 @@ async fn main () -> Result <()> { let mut event_pump = sdl_context.event_pump ().unwrap (); let mut time_step = TimeStep::new (60, 1000); - let mut graphics_frames = 0; - - let uniform_names = { - vec! [ - (uniforms::MVP, "uni_mvp"), - (uniforms::OBJECT_SPACE_LIGHT, "uni_object_space_light"), - (uniforms::OBJECT_SPACE_SKY, "uni_object_space_sky"), - (uniforms::ALBEDO, "uni_albedo"), - (uniforms::MIN_ALBEDO, "uni_min_albedo"), - (uniforms::MIN_BRIGHT, "uni_min_bright"), - (uniforms::TEXTURE, "uni_texture"), - ] - }; - - let attr_names = { - vec! [ - (attributes::POS, "attr_pos"), - (attributes::UV, "attr_uv"), - (attributes::NORMAL, "attr_normal"), - ] - }; - - let shaders: Vec <_> = [ - ("shaders/pumpkin-vert.glsl", "shaders/pumpkin-frag.glsl"), - ("shaders/shadow-vert.glsl", "shaders/shadow-frag.glsl"), - ("shaders/terrain-vert.glsl", "shaders/terrain-frag.glsl"), - ].into_iter () - .map (|(v, f)| { - ShaderClosure::new (shader_from_files (v, f), &uniform_names, &attr_names) - }) - .collect (); - - let mesh_cube = renderable_from_iqm_file ("cube.iqm"); - let mesh_sky = renderable_from_iqm_file ("sky-sphere.iqm"); - let mesh_sphere = renderable_from_iqm_file ("sphere.iqm"); let level = gltf::Gltf::open ("gltf/level-00.gltf")?; for scene in level.scenes () { @@ -293,67 +92,7 @@ async fn main () -> Result <()> { } } - let passes = vec![ - // Clear everything - Pass::default () - .color_mask ([1, 1, 1, 1]) - .depth_mask (1) - .clone (), - // Draw world - Pass::default () - .shader (&shaders [0]) - .flags ([ - (gl::CULL_FACE, true), - (gl::DEPTH_TEST, true), - (gl::TEXTURE_2D, true), - (gl::STENCIL_TEST, false), - ].into_iter ()) - .front_face (FrontFace::Ccw) - .color_mask ([1, 1, 1, 1]) - .depth_mask (1) - .clone (), - ]; - - let text_stream = TriangleStream { - verts: gpu_buffers::VertexBuffer::streaming (4 * 5 * 6 * 1024), - indices: { - let quad = [ - 0, 1, 2, - 0, 2, 3, - ]; - - let v: Vec = (0u32..1024).map (|i| { - quad.iter ().map (move |j| 4 * i + j) - }).flatten ().collect (); - gpu_buffers::IndexBuffer::from_slice_u32 (&v) - } - }; - - 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; - glezz::enable_vertex_attrib_array (attrs [attributes::POS]); - glezz::enable_vertex_attrib_array (attrs [attributes::UV]); - glezz::enable_vertex_attrib_array (attrs [attributes::NORMAL]); - }); - - let mut graphics = GameGraphics { - mesh_cube, - mesh_sky, - mesh_sphere, - passes, - shader_lookup, - shaders, - text_stream, - texture_crate: Texture::from_file ("crate.png"), - texture_earth: Texture::from_file ("earth.png"), - texture_sky: Texture::from_file ("sky.png"), - frames: 0, - }; + let mut graphics = Graphics::new (); let mut gl_state = Default::default (); let mut game_state = GameState::default (); @@ -478,15 +217,3 @@ struct TriangleStream { pub verts: gpu_buffers::VertexBuffer, pub indices: gpu_buffers::IndexBuffer, } - -fn color_from_255 (rgb: V) -> Vec3 -where V: Into -{ - let rgb: Vec3 = rgb.into (); - - Vec3::from (( - rgb.x / 255.0, - rgb.y / 255.0, - rgb.z / 255.0 - )) -}