summaryrefslogtreecommitdiff
path: root/render/src/texture.rs
diff options
context:
space:
mode:
Diffstat (limited to 'render/src/texture.rs')
-rw-r--r--render/src/texture.rs137
1 files changed, 7 insertions, 130 deletions
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<dyn Error>),
}
@@ -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<TextureManager>,
- 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<f32, TextureError> {
- 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<TextureManager>,
- 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<TextureId, TextureError> {
- 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<TextureId>> {
- 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;
}
}