You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

120 lines
3.6 KiB

  1. use glc::{
  2. matrix::Matrix4f,
  3. misc::{BindGuard, Bindable},
  4. shader::{Program, Type, Uniform},
  5. texture::Texture,
  6. vector::Vector4f,
  7. };
  8. use space_crush_common::{
  9. components::{Asteroid, AsteroidType, Owned, Player, Position},
  10. misc::LogResult,
  11. };
  12. use specs::{prelude::*, ReadExpect, ReadStorage, System, World};
  13. use crate::{
  14. constants::{PLAYER_COLOR_DEFAULT, UNIFORM_BUFFER_INDEX_CAMERA, UNIFORM_BUFFER_INDEX_UNIFORM},
  15. misc::WorldHelper,
  16. resources::Geometry,
  17. Error,
  18. };
  19. pub struct Asteroids {
  20. program: Program,
  21. texture_metal: Texture,
  22. texture_crystal: Texture,
  23. location_model: gl::GLint,
  24. location_glow_color: gl::GLint,
  25. }
  26. impl Asteroids {
  27. pub fn new(world: &World) -> Result<Self, Error> {
  28. let program = world.load_program(vec![
  29. (Type::Vertex, "resources/shader/asteroid/vert.glsl"),
  30. (Type::Fragment, "resources/shader/asteroid/frag.glsl"),
  31. ])?;
  32. program.uniform_block_binding("Camera", UNIFORM_BUFFER_INDEX_CAMERA)?;
  33. program.uniform_block_binding("Global", UNIFORM_BUFFER_INDEX_UNIFORM)?;
  34. let location_model = program.uniform_location("uModel")?;
  35. let location_glow_color = program.uniform_location("uGlowColor")?;
  36. program.bind();
  37. program.uniform("uTexture", Uniform::Texture(0))?;
  38. program.unbind();
  39. let texture_metal = world.load_texture("resources/textures/asteroid_metal.png")?;
  40. let texture_crystal = world.load_texture("resources/textures/asteroid_crystal.png")?;
  41. Ok(Self {
  42. program,
  43. texture_metal,
  44. texture_crystal,
  45. location_model,
  46. location_glow_color,
  47. })
  48. }
  49. }
  50. #[derive(SystemData)]
  51. pub struct AsteroidsData<'a> {
  52. geometry: ReadExpect<'a, Geometry>,
  53. position: ReadStorage<'a, Position>,
  54. asteroid: ReadStorage<'a, Asteroid>,
  55. owned: ReadStorage<'a, Owned>,
  56. player: ReadStorage<'a, Player>,
  57. }
  58. impl<'a> System<'a> for Asteroids {
  59. type SystemData = AsteroidsData<'a>;
  60. fn run(&mut self, data: Self::SystemData) {
  61. let AsteroidsData {
  62. geometry,
  63. position,
  64. asteroid,
  65. owned,
  66. player,
  67. } = data;
  68. gl::enable(gl::BLEND);
  69. gl::blend_func(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA);
  70. let _guard = BindGuard::new(&self.program);
  71. for (position, asteroid, owned) in (&position, &asteroid, owned.maybe()).join() {
  72. let p_x = position.pos.x;
  73. let p_y = position.pos.y;
  74. let s = position.size;
  75. let _guard = match asteroid.type_ {
  76. AsteroidType::Metal => BindGuard::new(&self.texture_metal),
  77. AsteroidType::Crystal => BindGuard::new(&self.texture_crystal),
  78. };
  79. let c = match owned.and_then(|owned| player.get(owned.owner)) {
  80. Some(pv) => &pv.color,
  81. None => &*PLAYER_COLOR_DEFAULT,
  82. };
  83. let m = Matrix4f::new(
  84. Vector4f::new(s, 0.0, 0.0, 0.0),
  85. Vector4f::new(0.0, s, 0.0, 0.0),
  86. Vector4f::new(0.0, 0.0, s, 0.0),
  87. Vector4f::new(p_x, p_y, 0.0, 1.0),
  88. );
  89. self.program
  90. .uniform(self.location_glow_color, Uniform::Vector4f(&c))
  91. .error("Error while updating glow color");
  92. self.program
  93. .uniform(self.location_model, Uniform::Matrix4f(&m))
  94. .error("Error while updating model matrix");
  95. geometry.render_quad();
  96. }
  97. gl::disable(gl::BLEND);
  98. }
  99. }