From b15126ef266cc9e364e9fe155fd6941779249579 Mon Sep 17 00:00:00 2001 From: Micha White Date: Wed, 12 Oct 2022 12:42:49 -0400 Subject: Removed WgpuTextures --- src/texture.rs | 211 ++++++++++++++++++++------------------------------------- 1 file changed, 75 insertions(+), 136 deletions(-) (limited to 'src/texture.rs') diff --git a/src/texture.rs b/src/texture.rs index e0ceb7d..060a029 100644 --- a/src/texture.rs +++ b/src/texture.rs @@ -61,135 +61,43 @@ impl From for TextureError { } } +const fn extent_3d(width: u32, height: u32) -> wgpu::Extent3d { + wgpu::Extent3d { + width, + height, + depth_or_array_layers: 1, + } +} + // TODO make this Debug // TODO make these resizable -// TODO this could probably be moved into WgpuTextures -pub struct TextureAtlas<'a> { - packer: TexturePacker<'a, image::RgbaImage, TextureId>, +pub struct TextureAtlas { + packer: TexturePacker<'static, image::RgbaImage, TextureId>, + diffuse_texture: wgpu::Texture, + diffuse_bind_group: wgpu::BindGroup, image: RgbaImage, width: u32, height: u32, -} - -impl<'a> Default for TextureAtlas<'a> { - fn default() -> Self { - Self::new(1024, 1024) - } + changed: bool, } macro_rules! texture_info { ($name: ident, $prop: ident) => { - pub fn $name(&self, id: TextureId) -> Option { + pub fn $name(&self, id: TextureId) -> Option { let frame = self.texture_frame(id)?; - Some(frame.frame.$prop) + let property = frame.frame.$prop; + let value = property as f32; + Some(value) } }; } -impl<'a> TextureAtlas<'a> { +impl TextureAtlas { /// Creates a new texture atlas, with the given size // TODO why is this u32? - pub fn new(width: u32, height: u32) -> Self { - Self { - packer: TexturePacker::new_skyline(TexturePackerConfig { - max_width: width, - max_height: height, - ..Default::default() - }), - width, - height, - image: RgbaImage::from_raw( - width, - height, - vec![0; 4 * width as usize * height as usize], - ) - .unwrap(), - } - } - - // TODO support RGBA16 - pub fn load_from_memory( - &mut self, - buf: &[u8], - format: ImageFormat, - ) -> Result { - let img = image::load_from_memory_with_format(buf, format.format())?.into_rgba8(); - let id = TextureId::new(); - self.packer - .pack_own(id, img) - .map_err(TextureError::TextureTooLarge)?; - - Ok(id) - } - - fn texture_frame(&self, id: TextureId) -> Option<&texture_packer::Frame> { - self.packer.get_frame(&id) - } - - texture_info!(texture_width, w); - texture_info!(texture_height, h); - texture_info!(texture_x, x); - texture_info!(texture_y, y); - - const fn extent_3d(&self) -> wgpu::Extent3d { - wgpu::Extent3d { - width: self.width, - height: self.height, - depth_or_array_layers: 1, - } - } - - 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(()) - } - - fn clear(&mut self) { - self.packer = TexturePacker::new_skyline(TexturePackerConfig { - max_width: self.width, - max_height: self.height, - ..Default::default() - }); - } - - fn image(&mut self) -> ExportResult<&RgbaImage> { - self.fill_image()?; - Ok(&self.image) - } -} - -pub struct WgpuTextures { - atlases: TextureAtlas<'static>, - diffuse_texture: wgpu::Texture, - diffuse_bind_group: wgpu::BindGroup, - changed: bool, -} - -macro_rules! get_info { - ($name: ident, $divisor: ident) => { - // TODO try to remove this - #[allow(clippy::cast_precision_loss)] - pub fn $name(&self, id: TextureId) -> Option { - self.atlases - .$name(id) - .map(|u| u as f32 / self.atlases.extent_3d().$divisor as f32) - } - }; -} - -impl WgpuTextures { // TODO this is still too large pub fn new(device: &wgpu::Device, width: u32, height: u32) -> (Self, wgpu::BindGroupLayout) { - let atlases = TextureAtlas::new(width, height); - let atlas_size = atlases.extent_3d(); - + let atlas_size = extent_3d(width, height); let diffuse_texture = device.create_texture(&wgpu::TextureDescriptor { label: Some("Diffuse Texture"), size: atlas_size, @@ -246,37 +154,73 @@ impl WgpuTextures { ( Self { - atlases, + packer: TexturePacker::new_skyline(TexturePackerConfig { + max_width: width, + max_height: height, + ..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, ) } - /// Loads a texture from memory, in the given file format - /// - /// # Errors - /// - /// This returns an error if the texture is not in the given format, or if - /// the texture is so large that it cannot fit in the texture atlas. - pub fn texture_from_memory( + pub(crate) const fn bind_group(&self) -> &wgpu::BindGroup { + &self.diffuse_bind_group + } + + // TODO support RGBA16 + pub fn load_from_memory( &mut self, - texture: &[u8], + buf: &[u8], format: ImageFormat, ) -> Result { - self.changed = true; - self.atlases.load_from_memory(texture, format) + let img = image::load_from_memory_with_format(buf, format.format())?.into_rgba8(); + let id = TextureId::new(); + self.packer + .pack_own(id, img) + .map_err(TextureError::TextureTooLarge)?; + + Ok(id) } - get_info!(texture_width, width); - get_info!(texture_height, height); - get_info!(texture_x, width); - get_info!(texture_y, height); + fn texture_frame(&self, id: TextureId) -> Option<&texture_packer::Frame> { + self.packer.get_frame(&id) + } - pub const fn bind_group(&self) -> &wgpu::BindGroup { - &self.diffuse_bind_group + texture_info!(texture_width, w); + texture_info!(texture_height, h); + texture_info!(texture_x, x); + texture_info!(texture_y, y); + + 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(()) + } + + fn clear(&mut self) { + self.packer = TexturePacker::new_skyline(TexturePackerConfig { + max_width: self.width, + max_height: self.height, + ..Default::default() + }); } #[profiling::function] @@ -289,10 +233,10 @@ impl WgpuTextures { return; } - let atlas_size = self.atlases.extent_3d(); + let atlas_size = extent_3d(self.width, self.height); // put the packed texture into the base image - let Ok(atlas) = self.atlases.image() else { return }; + drop(self.fill_image()); // copy that to the gpu queue.write_texture( @@ -302,7 +246,7 @@ impl WgpuTextures { origin: wgpu::Origin3d::ZERO, aspect: wgpu::TextureAspect::All, }, - atlas.as_bytes(), + self.image.as_bytes(), wgpu::ImageDataLayout { offset: 0, bytes_per_row: NonZeroU32::new(atlas_size.width * 4), @@ -313,9 +257,4 @@ impl WgpuTextures { self.changed = false; } - - pub fn clear_textures(&mut self) { - self.changed = true; - self.atlases.clear(); - } } -- cgit v1.2.3