2023-12-24 16:18:36 -08:00

91 lines
2.7 KiB
Rust

use anyhow::Result;
use std::{collections::HashMap, num::NonZeroU32, path::PathBuf};
use wgpu::BindGroupLayout;
use super::{loader::TextureLoader, Texture, TextureArrayConfig};
pub struct TextureArray {
pub bind_group: wgpu::BindGroup,
pub bind_group_layout: BindGroupLayout,
textures: HashMap<String, Texture>,
config: TextureArrayConfig,
}
impl TextureArray {
const INDEX_PATH: &'static str = "assets.ignore";
pub fn get_starfield(&self) -> Texture {
return self.get_texture(&self.config.starfield);
}
pub fn get_texture(&self, name: &str) -> Texture {
match self.textures.get(name) {
Some(x) => *x,
None => self.get_texture(&self.config.error),
}
}
pub fn new(device: &wgpu::Device, queue: &wgpu::Queue) -> Result<Self> {
// Load all textures
let loader = TextureLoader::load(device, queue, &PathBuf::from(Self::INDEX_PATH))?;
let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
address_mode_u: wgpu::AddressMode::ClampToEdge,
address_mode_v: wgpu::AddressMode::ClampToEdge,
address_mode_w: wgpu::AddressMode::ClampToEdge,
mag_filter: wgpu::FilterMode::Linear,
min_filter: wgpu::FilterMode::Nearest,
mipmap_filter: wgpu::FilterMode::Nearest,
..Default::default()
});
let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
label: Some("texture_bind_group_layout"),
entries: &[
// Texture data
wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Texture {
multisampled: false,
view_dimension: wgpu::TextureViewDimension::D2,
sample_type: wgpu::TextureSampleType::Float { filterable: true },
},
count: NonZeroU32::new(loader.texture_data.len() as u32),
},
// Texture sampler
wgpu::BindGroupLayoutEntry {
binding: 1,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
count: NonZeroU32::new(loader.texture_data.len() as u32),
},
],
});
let views: Vec<&wgpu::TextureView> = loader.texture_data.iter().map(|x| &x.view).collect();
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
label: Some("texture_bind_group"),
layout: &bind_group_layout,
entries: &[
wgpu::BindGroupEntry {
binding: 0,
// Array of all views
resource: wgpu::BindingResource::TextureViewArray(&views),
},
wgpu::BindGroupEntry {
binding: 1,
resource: wgpu::BindingResource::SamplerArray(&[&sampler].repeat(views.len())),
},
],
});
return Ok(Self {
bind_group,
bind_group_layout,
textures: loader.textures,
config: loader.config,
});
}
}