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.

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