rust/lib-hedgewars-engine/src/render/gear.rs
changeset 15784 84c07aa94b61
parent 15782 ff1432e873bd
child 15785 f6af9d05b03c
--- a/rust/lib-hedgewars-engine/src/render/gear.rs	Fri Nov 13 02:52:15 2020 +0300
+++ b/rust/lib-hedgewars-engine/src/render/gear.rs	Fri Nov 13 20:54:00 2020 +0300
@@ -1,7 +1,10 @@
 use crate::render::{
     atlas::{AtlasCollection, SpriteIndex, SpriteLocation},
     camera::Camera,
-    gl::{Texture2D, TextureDataType, TextureFilter, TextureFormat, TextureInternalFormat},
+    gl::{
+        Buffer, BufferType, BufferUsage, InputElement, InputFormat, InputLayout, PipelineState,
+        Shader, Texture2D, TextureDataType, TextureFilter, TextureFormat, TextureInternalFormat,
+    },
 };
 
 use integral_geometry::{Rect, Size};
@@ -14,9 +17,38 @@
     fs::{read_dir, File},
     io,
     io::BufReader,
+    mem::size_of,
     path::{Path, PathBuf},
 };
 
+const VERTEX_SHADER: &'static str = r#"
+#version 330 core
+
+layout(location = 0) in vec2 position;
+
+uniform mat4 projection;
+
+void main() {
+	gl_Position = projection * vec4(position, 0.0, 1.0);
+}
+"#;
+
+const PIXEL_SHADER: &'static str = r#"
+#version 330 core
+
+out vec4 outColor;
+
+void main() {
+	 outColor = vec4(0.0, 1.0, 0.0, 1.0);
+}
+"#;
+
+#[repr(C)]
+#[derive(Copy, Clone)]
+struct Vertex {
+    pos: [f32; 2],
+}
+
 #[derive(PartialEq, Debug, Clone, Copy)]
 pub enum SpriteId {
     Mine = 0,
@@ -38,9 +70,26 @@
 
 const MAX_SPRITES: usize = SpriteId::MaxSprite as usize + 1;
 
+pub struct GearEntry {
+    position: [f32; 2],
+    size: Size,
+}
+
+impl GearEntry {
+    pub fn new(x: f32, y: f32, size: Size) -> Self {
+        Self {
+            position: [x, y],
+            size,
+        }
+    }
+}
+
 pub struct GearRenderer {
     atlas: AtlasCollection,
     allocation: Box<[SpriteLocation; MAX_SPRITES]>,
+    shader: Shader,
+    layout: InputLayout,
+    vertex_buffer: Buffer,
 }
 
 struct SpriteData {
@@ -85,11 +134,81 @@
             allocation[*sprite as usize] = (texture_index, rect);
         }
 
-        Self { atlas, allocation }
+        let shader = Shader::new(VERTEX_SHADER, Some(PIXEL_SHADER), &[]).unwrap();
+
+        let layout = InputLayout::new(vec![
+            // position
+            InputElement {
+                shader_slot: 0,
+                buffer_slot: 0,
+                format: InputFormat::Float(gl::FLOAT, false),
+                components: 2,
+                stride: size_of::<Vertex>() as u32,
+                offset: 0,
+            },
+        ]);
+
+        let vertex_buffer = Buffer::empty(BufferType::Array, BufferUsage::DynamicDraw);
+
+        Self {
+            atlas,
+            allocation,
+            shader,
+            layout,
+            vertex_buffer,
+        }
     }
 
-    pub fn render(&mut self, camera: &Camera) {
+    pub fn render(&mut self, camera: &Camera, entries: &[GearEntry]) {
         let projection = camera.projection();
+        self.shader.bind();
+        self.shader.set_matrix("projection", projection.as_ptr());
+
+        let mut data = Vec::with_capacity(entries.len() * 12);
+
+        for entry in entries {
+            let vertices = [
+                [
+                    entry.position[0] - entry.size.width as f32 / 2.0,
+                    entry.position[1] + entry.size.height as f32 / 2.0,
+                ],
+                [
+                    entry.position[0] + entry.size.width as f32 / 2.0,
+                    entry.position[1] + entry.size.height as f32 / 2.0,
+                ],
+                [
+                    entry.position[0] - entry.size.width as f32 / 2.0,
+                    entry.position[1] - entry.size.height as f32 / 2.0,
+                ],
+                [
+                    entry.position[0] + entry.size.width as f32 / 2.0,
+                    entry.position[1] - entry.size.height as f32 / 2.0,
+                ],
+            ];
+
+            data.extend_from_slice(&[
+                vertices[0][0],
+                vertices[0][1],
+                vertices[1][0],
+                vertices[1][1],
+                vertices[2][0],
+                vertices[2][1],
+                vertices[1][0],
+                vertices[1][1],
+                vertices[3][0],
+                vertices[3][1],
+                vertices[2][0],
+                vertices[2][1],
+            ]);
+        }
+
+        self.vertex_buffer.write_typed(&data);
+        let _buffer_bind = self.layout.bind(&[(0, &self.vertex_buffer)], None);
+        let _state = PipelineState::new().with_blend();
+
+        unsafe {
+            gl::DrawArrays(gl::TRIANGLES, 0, entries.len() as i32 * 2);
+        }
     }
 }