# HG changeset patch # User alfadur # Date 1605290040 -10800 # Node ID 84c07aa94b612caa82e8be2ffac016c5d38648a7 # Parent e7eb0cd5b0e41911b753b7aa20c6d8946e3965e1 start drawing gears diff -r e7eb0cd5b0e4 -r 84c07aa94b61 rust/hwphysics/src/lib.rs --- a/rust/hwphysics/src/lib.rs Fri Nov 13 02:52:15 2020 +0300 +++ b/rust/hwphysics/src/lib.rs Fri Nov 13 20:54:00 2020 +0300 @@ -11,7 +11,7 @@ use crate::{ collision::CollisionProcessor, common::{GearAllocator, GearId, Millis}, - data::GearDataManager, + data::{DataIterator, GearDataManager, TypeIter}, physics::PhysicsProcessor, time::TimeProcessor, }; @@ -67,6 +67,11 @@ pub fn add_gear_data(&mut self, gear_id: GearId, data: &T) { self.data.add(gear_id, data); } + + #[inline] + pub fn iter_data(&mut self) -> DataIterator { + self.data.iter() + } } #[cfg(test)] diff -r e7eb0cd5b0e4 -r 84c07aa94b61 rust/lib-hedgewars-engine/src/render/gear.rs --- 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::() 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); + } } } diff -r e7eb0cd5b0e4 -r 84c07aa94b61 rust/lib-hedgewars-engine/src/render/gl.rs --- a/rust/lib-hedgewars-engine/src/render/gl.rs Fri Nov 13 02:52:15 2020 +0300 +++ b/rust/lib-hedgewars-engine/src/render/gl.rs Fri Nov 13 20:54:00 2020 +0300 @@ -417,14 +417,8 @@ return Err(String::from_utf8_unchecked(log)); } - //gl::DetachShader(program, vs); - if let Some(ps) = ps { - //gl::DetachShader(program, ps); - } - gl::UseProgram(program); - // after linking we setup sampler bindings as specified in the shader for bind in bindings { match bind { VariableBinding::Uniform(name, id) => { diff -r e7eb0cd5b0e4 -r 84c07aa94b61 rust/lib-hedgewars-engine/src/render/map.rs --- a/rust/lib-hedgewars-engine/src/render/map.rs Fri Nov 13 02:52:15 2020 +0300 +++ b/rust/lib-hedgewars-engine/src/render/map.rs Fri Nov 13 20:54:00 2020 +0300 @@ -13,7 +13,6 @@ use std::num::NonZeroU32; -// TODO: temp const VERTEX_SHADER: &'static str = r#" #version 150 @@ -48,7 +47,7 @@ } "#; -pub struct MapTile { +struct MapTile { // either index into GL texture array or emulated [Texture; N] texture_index: u32, @@ -58,13 +57,13 @@ #[repr(C)] #[derive(Copy, Clone)] -pub struct TileVertex { +struct TileVertex { pos: [f32; 2], // doesn't hurt to include another float, just in case.. uv: [f32; 3], } -pub struct DrawTile { +struct DrawTile { texture_index: u32, index_len: u32, } diff -r e7eb0cd5b0e4 -r 84c07aa94b61 rust/lib-hedgewars-engine/src/world.rs --- a/rust/lib-hedgewars-engine/src/world.rs Fri Nov 13 02:52:15 2020 +0300 +++ b/rust/lib-hedgewars-engine/src/world.rs Fri Nov 13 20:54:00 2020 +0300 @@ -12,7 +12,7 @@ }; use lfprng::LaggedFibonacciPRNG; -use crate::render::{camera::Camera, GearRenderer, MapRenderer}; +use crate::render::{camera::Camera, GearEntry, GearRenderer, MapRenderer}; struct GameState { land: Land2D, @@ -32,6 +32,7 @@ map_renderer: Option, gear_renderer: Option, camera: Camera, + gear_entries: Vec, } impl World { @@ -43,6 +44,7 @@ map_renderer: None, gear_renderer: None, camera: Camera::new(), + gear_entries: vec![], } } @@ -125,9 +127,26 @@ renderer.render(&self.camera); } + + self.gear_entries.clear(); + let mut gear_entries = std::mem::take(&mut self.gear_entries); + if let Some(ref mut renderer) = self.gear_renderer { - renderer.render(&self.camera) + if let Some(ref mut state) = self.game_state { + state + .physics + .iter_data() + .run(|(pos,): (&mut PositionData,)| { + gear_entries.push(GearEntry::new( + f64::from(pos.0.x()) as f32, + f64::from(pos.0.y()) as f32, + Size::square(128), + )) + }); + } + renderer.render(&self.camera, &gear_entries); } + self.gear_entries = gear_entries; } fn create_gear(&mut self, position: Point) {