# HG changeset patch # User alfadur # Date 1564784025 -10800 # Node ID 16bd389fc7350e89ae09302aff01054f3704c4fc # Parent 6382a14c9e8315f6975a16fc8d01ea9ac79b5081 ship the atlas to the gpu diff -r 6382a14c9e83 -r 16bd389fc735 rust/integral-geometry/src/lib.rs --- a/rust/integral-geometry/src/lib.rs Sat Aug 03 00:54:29 2019 +0300 +++ b/rust/integral-geometry/src/lib.rs Sat Aug 03 01:13:45 2019 +0300 @@ -171,6 +171,14 @@ pub fn contains(&self, other: Self) -> bool { self.width >= other.width && self.height >= other.height } + + #[inline] + pub fn join(&self, other: Self) -> Self { + Self { + width: max(self.width, other.width), + height: max(self.height, other.height) + } + } } #[derive(PartialEq, Eq, Clone, Copy, Debug)] diff -r 6382a14c9e83 -r 16bd389fc735 rust/lib-hedgewars-engine/src/render/atlas.rs --- a/rust/lib-hedgewars-engine/src/render/atlas.rs Sat Aug 03 00:54:29 2019 +0300 +++ b/rust/lib-hedgewars-engine/src/render/atlas.rs Sat Aug 03 01:13:45 2019 +0300 @@ -250,6 +250,10 @@ } } + pub fn get_rect(&self, index: SpriteIndex) -> Option<(u32, Rect)> { + self.rects.get(index as usize).cloned() + } + pub fn used_space(&self) -> String { self.atlases .iter() diff -r 6382a14c9e83 -r 16bd389fc735 rust/lib-hedgewars-engine/src/render/gear.rs --- a/rust/lib-hedgewars-engine/src/render/gear.rs Sat Aug 03 00:54:29 2019 +0300 +++ b/rust/lib-hedgewars-engine/src/render/gear.rs Sat Aug 03 01:13:45 2019 +0300 @@ -1,10 +1,14 @@ -use super::atlas::AtlasCollection; +use super::{atlas::AtlasCollection, gl::Texture2D}; use crate::render::camera::Camera; -use integral_geometry::Size; +use integral_geometry::{Rect, Size}; +use crate::render::atlas::SpriteIndex; use png::{ColorType, Decoder, DecodingError}; +use std::path::PathBuf; use std::{ + collections::HashMap, + ffi::OsString, fs::{read_dir, File}, io, io::BufReader, @@ -15,21 +19,43 @@ atlas: AtlasCollection, } -const ATLAS_SIZE: Size = Size::square(1024); +struct SpriteData { + size: Size, + filename: PathBuf, +} + +const ATLAS_SIZE: Size = Size::square(2024); impl GearRenderer { pub fn new() -> Self { + let mut lookup = Vec::with_capacity(2048); + let mut atlas = AtlasCollection::new(ATLAS_SIZE); - let sprites = load_sprites(Path::new("../../share/hedgewars/Data/Graphics/")) + let mut sprites = load_sprites(Path::new("../../share/hedgewars/Data/Graphics/")) .expect("Unable to load Graphics"); - for sprite in &sprites { - atlas.insert_sprite(*sprite); + let max_size = sprites + .iter() + .fold(Size::EMPTY, |size, sprite| size.join(sprite.size)); + for sprite in sprites.drain(..) { + lookup.push((sprite.filename, atlas.insert_sprite(sprite.size).unwrap())); } + println!( "Filled atlas with {} sprites:\n{}", sprites.len(), atlas.used_space() ); + + let texture = Texture2D::new(max_size, gl::RGBA8, gl::LINEAR); + + let mut pixels = Vec::with_capacity(max_size.area()).into_boxed_slice(); + for (path, sprite_index) in lookup.drain(..) { + if let Some((atlas_index, rect)) = atlas.get_rect(sprite_index) { + load_sprite_pixels(&path, &mut pixels[..]).expect("Unable to load Graphics"); + texture.update(rect, &pixels, 0, gl::RGBA, gl::UNSIGNED_BYTE); + } + } + Self { atlas } } @@ -38,7 +64,16 @@ } } -fn load_sprite(path: &Path) -> io::Result { +fn load_sprite_pixels(path: &Path, buffer: &mut [u8]) -> io::Result<()> { + let decoder = Decoder::new(BufReader::new(File::open(path)?)); + let (info, mut reader) = decoder.read_info()?; + + let size = Size::new(info.width as usize, info.height as usize); + reader.next_frame(buffer)?; + Ok(()) +} + +fn load_sprite_size(path: &Path) -> io::Result { let decoder = Decoder::new(BufReader::new(File::open(path)?)); let (info, mut reader) = decoder.read_info()?; @@ -46,14 +81,18 @@ Ok(size) } -fn load_sprites(path: &Path) -> io::Result> { +fn load_sprites(path: &Path) -> io::Result> { let mut result = vec![]; for file in read_dir(path)? { let file = file?; if let Some(extension) = file.path().extension() { if extension == "png" { - let sprite = load_sprite(&file.path())?; - result.push(sprite); + let path = file.path(); + let sprite = load_sprite_size(&path)?; + result.push(SpriteData { + size: sprite, + filename: path, + }); } } } diff -r 6382a14c9e83 -r 16bd389fc735 rust/lib-hedgewars-engine/src/render/gl.rs --- a/rust/lib-hedgewars-engine/src/render/gl.rs Sat Aug 03 00:54:29 2019 +0300 +++ b/rust/lib-hedgewars-engine/src/render/gl.rs Sat Aug 03 01:13:45 2019 +0300 @@ -63,7 +63,7 @@ } impl Texture2D { - pub fn new(size: Size, internal_format: u32, format: u32, ty: u32, filter: u32) -> Self { + pub fn new(size: Size, internal_format: u32, filter: u32) -> Self { if let Some(handle) = new_texture() { unsafe { gl::BindTexture(gl::TEXTURE_2D, handle.get()); @@ -74,8 +74,8 @@ size.width as i32, size.height as i32, 0, - format as u32, - ty, + gl::RGBA, + gl::UNSIGNED_BYTE, std::ptr::null(), ) } diff -r 6382a14c9e83 -r 16bd389fc735 rust/lib-hedgewars-engine/src/render/map.rs --- a/rust/lib-hedgewars-engine/src/render/map.rs Sat Aug 03 00:54:29 2019 +0300 +++ b/rust/lib-hedgewars-engine/src/render/map.rs Sat Aug 03 01:13:45 2019 +0300 @@ -171,8 +171,7 @@ let texture = Texture2D::with_data( data, stride, - self.tile_size.width as u32, - self.tile_size.height as u32, + self.tile_size, gl::RGBA8, gl::RGBA, gl::UNSIGNED_BYTE,