@@ -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; | |||