--- 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<T: Clone + 'static>(&mut self, gear_id: GearId, data: &T) {
self.data.add(gear_id, data);
}
+
+ #[inline]
+ pub fn iter_data<T: TypeIter + 'static>(&mut self) -> DataIterator<T> {
+ self.data.iter()
+ }
}
#[cfg(test)]
--- 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);
+ }
}
}
--- 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) => {
--- 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,
}
--- 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<u32>,
@@ -32,6 +32,7 @@
map_renderer: Option<MapRenderer>,
gear_renderer: Option<GearRenderer>,
camera: Camera,
+ gear_entries: Vec<GearEntry>,
}
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) {