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