use glc::{ matrix::Matrix4f, misc::{BindGuard, Bindable}, shader::{Program, Type, Uniform}, texture::Texture, vector::Vector4f, }; use space_crush_common::{ components::{Owned, Planet, 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 Planets { program: Program, texture: Texture, location_model: gl::GLint, location_glow_color: gl::GLint, } impl Planets { pub fn new(world: &World) -> Result { let program = world.load_program(vec![ (Type::Vertex, "resources/shader/planet/vert.glsl"), (Type::Fragment, "resources/shader/planet/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 = world.load_texture("resources/textures/planet01.png")?; Ok(Self { program, texture, location_model, location_glow_color, }) } } #[derive(SystemData)] pub struct PlanetsData<'a> { geometry: ReadExpect<'a, Geometry>, position: ReadStorage<'a, Position>, planet: ReadStorage<'a, Planet>, owned: ReadStorage<'a, Owned>, player: ReadStorage<'a, Player>, } impl<'a> System<'a> for Planets { type SystemData = PlanetsData<'a>; fn run(&mut self, data: Self::SystemData) { let PlanetsData { geometry, position, planet, owned, player, } = data; gl::enable(gl::BLEND); gl::blend_func(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA); let _guard = BindGuard::new(&self.program); let _guard = BindGuard::new(&self.texture); for (p, _, owned) in (&position, &planet, owned.maybe()).join() { let p_x = p.pos.x; let p_y = p.pos.y; let s = p.size; 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); } }