| @@ -0,0 +1,28 @@ | |||
| #version 450 core | |||
| #pragma include ./shared.glsl | |||
| #pragma include ../misc/glow.glsl | |||
| #pragma include ../misc/global.glsl | |||
| const GlowArgs GLOW_ARGS = { | |||
| /* step0 */ 0.480, | |||
| /* step1 */ 0.975, | |||
| /* pulseSize0 */ 0.010, | |||
| /* pulseSize1 */ 0.050, | |||
| /* pulseTime */ 2.000, | |||
| }; | |||
| in FragmentData fragmentData; | |||
| uniform vec4 uGlowColor; | |||
| uniform sampler2D uTexture; | |||
| out vec4 outColor; | |||
| void main() { | |||
| float alpha = glow(GLOW_ARGS, fragmentData.texCoords - vec2(0.5), uGlobal.time); | |||
| vec4 glow = vec4(uGlowColor.rgb, uGlowColor.a * alpha); | |||
| vec4 tex = texture(uTexture, fragmentData.texCoords); | |||
| outColor = tex * tex.a + glow * (1.0 - tex.a); | |||
| } | |||
| @@ -0,0 +1,3 @@ | |||
| struct FragmentData { | |||
| vec2 texCoords; | |||
| }; | |||
| @@ -0,0 +1,17 @@ | |||
| #version 450 core | |||
| #pragma include ./shared.glsl | |||
| #pragma include ../misc/camera.glsl | |||
| const float GLOW_SIZE_FACTOR = 2.00; | |||
| in vec3 inPosition; | |||
| uniform mat4 uModel; | |||
| out FragmentData fragmentData; | |||
| void main() { | |||
| fragmentData.texCoords = inPosition.xy * GLOW_SIZE_FACTOR + vec2(0.5); | |||
| gl_Position = uCamera.projection * uCamera.view * uModel * vec4(2.0 * inPosition * GLOW_SIZE_FACTOR, 1.0); | |||
| } | |||
| @@ -12,7 +12,7 @@ pub use error::Error; | |||
| use debug::{Fleets as DebugFleets, Ships as DebugShips, Summary as DebugSummary}; | |||
| use misc::{Events, TextManager, Window}; | |||
| use render::{Init, Planets, Ships}; | |||
| use render::{Asteroids, Init, Planets, Ships}; | |||
| use resources::{Camera, Config, Geometry, State, Uniform}; | |||
| use systems::StateUpdate; | |||
| @@ -46,6 +46,7 @@ impl<'a, 'b> App<'a, 'b> { | |||
| .with(StateUpdate::new(world)?, "state_update", &[]) | |||
| .with_thread_local(Init::new(world)?) | |||
| .with_thread_local(Planets::new(world)?) | |||
| .with_thread_local(Asteroids::new(world)?) | |||
| .with_thread_local(Ships::new(world)?) | |||
| .with_thread_local(DebugShips::default()) | |||
| .with_thread_local(DebugFleets::default()) | |||
| @@ -28,6 +28,8 @@ fn main() -> Result<(), Error> { | |||
| } | |||
| fn run(vfs: Vfs) -> Result<(), Error> { | |||
| info!("Application initialization"); | |||
| let mut world = World::new(); | |||
| world.insert(vfs); | |||
| @@ -38,6 +40,8 @@ fn run(vfs: Vfs) -> Result<(), Error> { | |||
| create_world(&mut world); | |||
| } | |||
| info!("Application initialized"); | |||
| while app.is_running() { | |||
| world.maintain(); | |||
| @@ -56,7 +60,10 @@ fn create_world(world: &mut World) { | |||
| vector::{Vector2f, Vector4f}, | |||
| }; | |||
| use space_crush_common::{ | |||
| components::{Fleet, Owned, Planet, Player, Position, Ship, ShipType, Velocity}, | |||
| components::{ | |||
| Asteroid, AsteroidType, Fleet, Owned, Planet, Player, Position, Ship, ShipType, | |||
| Velocity, | |||
| }, | |||
| misc::{PersistWorld, Persistence}, | |||
| }; | |||
| use specs::{saveload::MarkedBuilder, Builder}; | |||
| @@ -68,6 +75,38 @@ fn create_world(world: &mut World) { | |||
| }) | |||
| .build(); | |||
| world | |||
| .create_entity() | |||
| .marked::<<PersistWorld as Persistence>::Marker>() | |||
| .with(Position { | |||
| pos: Vector2f::new(500.0, -500.0), | |||
| size: 100.0, | |||
| }) | |||
| .with(Fleet { | |||
| orbit_min: 125.0, | |||
| orbit_max: 175.0, | |||
| }) | |||
| .with(Asteroid { | |||
| type_: AsteroidType::Metal, | |||
| }) | |||
| .build(); | |||
| world | |||
| .create_entity() | |||
| .marked::<<PersistWorld as Persistence>::Marker>() | |||
| .with(Position { | |||
| pos: Vector2f::new(500.0, 500.0), | |||
| size: 100.0, | |||
| }) | |||
| .with(Fleet { | |||
| orbit_min: 125.0, | |||
| orbit_max: 175.0, | |||
| }) | |||
| .with(Asteroid { | |||
| type_: AsteroidType::Crystal, | |||
| }) | |||
| .build(); | |||
| let planet = world | |||
| .create_entity() | |||
| .marked::<<PersistWorld as Persistence>::Marker>() | |||
| @@ -0,0 +1,119 @@ | |||
| use glc::{ | |||
| matrix::Matrix4f, | |||
| misc::{BindGuard, Bindable}, | |||
| shader::{Program, Type, Uniform}, | |||
| texture::Texture, | |||
| vector::Vector4f, | |||
| }; | |||
| use space_crush_common::{ | |||
| components::{Asteroid, AsteroidType, Owned, Player, Position}, | |||
| misc::LogResult, | |||
| }; | |||
| use specs::{prelude::*, ReadExpect, ReadStorage, System, World}; | |||
| use crate::{ | |||
| constants::{PLAYER_COLOR_DEFAULT, UNIFORM_BUFFER_INDEX_CAMERA, UNIFORM_BUFFER_INDEX_UNIFORM}, | |||
| misc::WorldHelper, | |||
| resources::Geometry, | |||
| Error, | |||
| }; | |||
| pub struct Asteroids { | |||
| program: Program, | |||
| texture_metal: Texture, | |||
| texture_crystal: Texture, | |||
| location_model: gl::GLint, | |||
| location_glow_color: gl::GLint, | |||
| } | |||
| impl Asteroids { | |||
| pub fn new(world: &World) -> Result<Self, Error> { | |||
| let program = world.load_program(vec![ | |||
| (Type::Vertex, "resources/shader/asteroid/vert.glsl"), | |||
| (Type::Fragment, "resources/shader/asteroid/frag.glsl"), | |||
| ])?; | |||
| program.uniform_block_binding("Camera", UNIFORM_BUFFER_INDEX_CAMERA)?; | |||
| program.uniform_block_binding("Global", UNIFORM_BUFFER_INDEX_UNIFORM)?; | |||
| let location_model = program.uniform_location("uModel")?; | |||
| let location_glow_color = program.uniform_location("uGlowColor")?; | |||
| program.bind(); | |||
| program.uniform("uTexture", Uniform::Texture(0))?; | |||
| program.unbind(); | |||
| let texture_metal = world.load_texture("resources/textures/asteroid_metal.png")?; | |||
| let texture_crystal = world.load_texture("resources/textures/asteroid_crystal.png")?; | |||
| Ok(Self { | |||
| program, | |||
| texture_metal, | |||
| texture_crystal, | |||
| location_model, | |||
| location_glow_color, | |||
| }) | |||
| } | |||
| } | |||
| #[derive(SystemData)] | |||
| pub struct AsteroidsData<'a> { | |||
| geometry: ReadExpect<'a, Geometry>, | |||
| position: ReadStorage<'a, Position>, | |||
| asteroid: ReadStorage<'a, Asteroid>, | |||
| owned: ReadStorage<'a, Owned>, | |||
| player: ReadStorage<'a, Player>, | |||
| } | |||
| impl<'a> System<'a> for Asteroids { | |||
| type SystemData = AsteroidsData<'a>; | |||
| fn run(&mut self, data: Self::SystemData) { | |||
| let AsteroidsData { | |||
| geometry, | |||
| position, | |||
| asteroid, | |||
| owned, | |||
| player, | |||
| } = data; | |||
| gl::enable(gl::BLEND); | |||
| gl::blend_func(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA); | |||
| let _guard = BindGuard::new(&self.program); | |||
| for (position, asteroid, owned) in (&position, &asteroid, owned.maybe()).join() { | |||
| let p_x = position.pos.x; | |||
| let p_y = position.pos.y; | |||
| let s = position.size; | |||
| let _guard = match asteroid.type_ { | |||
| AsteroidType::Metal => BindGuard::new(&self.texture_metal), | |||
| AsteroidType::Crystal => BindGuard::new(&self.texture_crystal), | |||
| }; | |||
| let c = match owned.and_then(|owned| player.get(owned.owner)) { | |||
| Some(pv) => &pv.color, | |||
| None => &*PLAYER_COLOR_DEFAULT, | |||
| }; | |||
| let m = Matrix4f::new( | |||
| Vector4f::new(s, 0.0, 0.0, 0.0), | |||
| Vector4f::new(0.0, s, 0.0, 0.0), | |||
| Vector4f::new(0.0, 0.0, s, 0.0), | |||
| Vector4f::new(p_x, p_y, 0.0, 1.0), | |||
| ); | |||
| self.program | |||
| .uniform(self.location_glow_color, Uniform::Vector4f(&c)) | |||
| .error("Error while updating glow color"); | |||
| self.program | |||
| .uniform(self.location_model, Uniform::Matrix4f(&m)) | |||
| .error("Error while updating model matrix"); | |||
| geometry.render_quad(); | |||
| } | |||
| gl::disable(gl::BLEND); | |||
| } | |||
| } | |||
| @@ -1,7 +1,9 @@ | |||
| mod asteroids; | |||
| mod init; | |||
| mod planets; | |||
| mod ships; | |||
| pub use asteroids::Asteroids; | |||
| pub use init::Init; | |||
| pub use planets::Planets; | |||
| pub use ships::Ships; | |||
| @@ -0,0 +1,17 @@ | |||
| use serde::{Deserialize, Serialize}; | |||
| use specs::{Component, HashMapStorage}; | |||
| #[derive(Clone, Debug, Serialize, Deserialize)] | |||
| pub struct Asteroid { | |||
| pub type_: Type, | |||
| } | |||
| #[derive(Clone, Debug, Serialize, Deserialize)] | |||
| pub enum Type { | |||
| Metal, | |||
| Crystal, | |||
| } | |||
| impl Component for Asteroid { | |||
| type Storage = HashMapStorage<Self>; | |||
| } | |||
| @@ -1,3 +1,4 @@ | |||
| mod asteroid; | |||
| mod fleet; | |||
| mod owned; | |||
| mod planet; | |||
| @@ -6,6 +7,7 @@ mod position; | |||
| mod ship; | |||
| mod velocity; | |||
| pub use asteroid::{Asteroid, Type as AsteroidType}; | |||
| pub use fleet::Fleet; | |||
| pub use owned::Owned; | |||
| pub use planet::Planet; | |||