From f8a80039c74332e2101a177ef3fde31ef2077224 Mon Sep 17 00:00:00 2001 From: Micha White Date: Thu, 15 Aug 2024 20:14:15 -0400 Subject: Lots a changes --- render/src/texture.rs | 137 +++----------------------------------------------- 1 file changed, 7 insertions(+), 130 deletions(-) (limited to 'render/src/texture.rs') diff --git a/render/src/texture.rs b/render/src/texture.rs index 76e77a8..90d23d1 100644 --- a/render/src/texture.rs +++ b/render/src/texture.rs @@ -1,30 +1,10 @@ use std::error::Error; -use std::num::NonZeroU32; -use std::sync::Arc; -use alligator_resources::texture::{LoadError, Rgba16Texture, TextureId, TextureManager}; -use image::{EncodableLayout, GenericImage, RgbaImage}; -use texture_packer::TexturePacker; -use texture_packer::{ - exporter::{ExportResult, ImageExporter}, - TexturePackerConfig, -}; +use image::{EncodableLayout, RgbaImage}; use thiserror::Error; -/// The texture did not fit in the texture atlas -#[derive(Debug, Error)] -#[error("{:?}", .0)] -pub struct PackError(PackErrorInternal); - -// TODO this can be removed when a new texture packer is made -type PackErrorInternal = impl std::fmt::Debug; - #[derive(Error, Debug)] pub enum TextureError { - #[error("{:?}", .0)] - TextureTooLarge(#[from] PackError), - #[error("{}", .0)] - BadImage(#[from] LoadError), #[error("Unexpected Error (this is a bug in alligator_render): {}", .0)] Unexpected(#[source] Box), } @@ -39,46 +19,18 @@ const fn extent_3d(width: u32, height: u32) -> wgpu::Extent3d { } /// A texture atlas, usable by the renderer -// TODO make this Debug // TODO make these resizable +#[derive(Debug)] pub struct TextureAtlas { - textures: Arc, - packer: TexturePacker<'static, Rgba16Texture, TextureId>, diffuse_texture: wgpu::Texture, diffuse_bind_group: wgpu::BindGroup, image: RgbaImage, - width: u32, - height: u32, - changed: bool, -} - -macro_rules! texture_info { - ($name: ident, $prop: ident, $divisor: ident) => { - pub fn $name(&mut self, id: TextureId) -> Result { - let frame = match self.texture_frame(id) { - Some(frame) => frame, - None => { - self.load_texture(id)?; - self.texture_frame(id).unwrap() - } - }; - let property = frame.frame.$prop; - let value = property as f32 / self.$divisor as f32; - Ok(value) - } - }; } impl TextureAtlas { /// Creates a new texture atlas, with the given size - // TODO why is this u32? // TODO this is still too large - pub fn new( - device: &wgpu::Device, - textures: Arc, - width: u32, - height: u32, - ) -> (Self, wgpu::BindGroupLayout) { + pub fn new(device: &wgpu::Device, width: u32, height: u32) -> (Self, wgpu::BindGroupLayout) { let atlas_size = extent_3d(width, height); let diffuse_texture = device.create_texture(&wgpu::TextureDescriptor { label: Some("Diffuse Texture"), @@ -137,26 +89,14 @@ impl TextureAtlas { ( Self { - textures, - packer: TexturePacker::new_skyline(TexturePackerConfig { - max_width: width, - max_height: height, - allow_rotation: false, - trim: false, - texture_padding: 0, - ..Default::default() - }), diffuse_texture, diffuse_bind_group, - width, - height, image: RgbaImage::from_raw( width, height, vec![0; 4 * width as usize * height as usize], ) .unwrap(), - changed: true, }, texture_bind_group_layout, ) @@ -167,68 +107,7 @@ impl TextureAtlas { &self.diffuse_bind_group } - /// Load a new subtexture from memory - pub fn load_texture(&mut self, id: TextureId) -> Result { - self.changed = true; - let img = self.textures.load_texture(id)?; - self.packer.pack_own(id, img).map_err(PackError)?; - Ok(id) - } - - /// Get the frame for s particular subtexture - fn texture_frame(&self, id: TextureId) -> Option<&texture_packer::Frame> { - self.packer.get_frame(&id) - } - - texture_info!(texture_width, w, width); - texture_info!(texture_height, h, height); - texture_info!(texture_x, x, width); - texture_info!(texture_y, y, height); - - /// Fill the cached image - fn fill_image(&mut self) -> ExportResult<()> { - let atlas = { - profiling::scope!("export atlas"); - ImageExporter::export(&self.packer)? - }; - profiling::scope!("copy image"); - self.image - .copy_from(&atlas, 0, 0) - .expect("image cache is too small"); - Ok(()) - } - - /// Clear the texture atlas, and give it a new size - pub fn clear(&mut self, width: u32, height: u32) { - self.changed = true; - self.width = width; - self.height = height; - self.packer = TexturePacker::new_skyline(TexturePackerConfig { - max_width: self.width, - max_height: self.height, - ..Default::default() - }); - } - - /// Fill the GPU texture atlas - #[profiling::function] - pub(crate) fn fill_textures(&mut self, queue: &wgpu::Queue) { - // saves time if nothing changed since the last time we did this - // FIXME This doesn't do much good once we get procedurally generated animation - // We'll have to create our own texture packer, with mutable subtextures, - // and more efficient algorithms. This'll also make frame times more consistent - if !self.changed { - return; - } - - let atlas_size = extent_3d(self.width, self.height); - - // put the packed texture into the base image - if let Err(e) = self.fill_image() { - log::error!("{}", e); - } - - // copy that to the gpu + pub(crate) fn fill_textures(&self, queue: &wgpu::Queue) { queue.write_texture( wgpu::ImageCopyTexture { texture: &self.diffuse_texture, @@ -239,12 +118,10 @@ impl TextureAtlas { self.image.as_bytes(), wgpu::ImageDataLayout { offset: 0, - bytes_per_row: NonZeroU32::new(atlas_size.width * 4), - rows_per_image: NonZeroU32::new(atlas_size.height), + bytes_per_row: Some(self.image.width() * 4), + rows_per_image: Some(self.image.height()), }, - atlas_size, + extent_3d(self.image.width(), self.image.height()), ); - - self.changed = false; } } -- cgit v1.2.3