Skip to main content

engine/
texture_manager.rs

1/**----------------------------------------------------------------------------
2*!  Texture asset management.
3*?  Manages all textures in the game. Loads textures using Texture,
4*?  stores them, and provides handles for safe access.
5*?  Manages bind groups for shader access for loading/creating a single GPU texture.
6*-----------------------------------------------------------------------------**/
7use crate::texture::Texture;
8
9//? Handle to a loaded texture. Encapsulates the index into the
10//? TextureManager's texture and bind group arrays.
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
12pub struct TextureHandle(pub(crate) usize);
13
14//? Texture asset manager.
15pub struct TextureManager {
16    pub(crate) textures: Vec<Texture>,
17    pub(crate) bind_groups: Vec<wgpu::BindGroup>,
18}
19
20//? Methods for loading textures and retrieving them by handle.
21impl TextureManager {
22    #[allow(dead_code)]
23    pub(crate) fn new() -> Self {
24        Self {
25            textures: Vec::new(),
26            bind_groups: Vec::new(),
27        }
28    }
29
30    //? Load a texture from image bytes and create a corresponding bind group.
31    //* Returns a TextureHandle that can be used to retrieve the texture and bind group later.
32    pub fn load_from_bytes(
33        &mut self,
34        device: &wgpu::Device,
35        queue: &wgpu::Queue,
36        bind_group_layout: &wgpu::BindGroupLayout,
37        bytes: &[u8],
38        label: Option<&str>,
39    ) -> Result<TextureHandle, image::ImageError> {
40        let texture = Texture::from_bytes(device, queue, bytes, label)?;
41
42        let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
43            label,
44            layout: bind_group_layout,
45            entries: &[
46                wgpu::BindGroupEntry {
47                    binding: 0,
48                    resource: wgpu::BindingResource::TextureView(&texture.view),
49                },
50                wgpu::BindGroupEntry {
51                    binding: 1,
52                    resource: wgpu::BindingResource::Sampler(&texture.sampler),
53                },
54            ],
55        });
56
57        let handle = TextureHandle(self.textures.len());
58        self.textures.push(texture);
59        self.bind_groups.push(bind_group);
60
61        Ok(handle)
62    }
63
64    pub fn get_texture(&self, handle: TextureHandle) -> Option<&Texture> {
65        self.textures.get(handle.0)
66    }
67
68    #[allow(dead_code)]
69    pub(crate) fn get_bind_group(&self, handle: TextureHandle) -> Option<&wgpu::BindGroup> {
70        self.bind_groups.get(handle.0)
71    }
72}