Added texture config file

master
Mark 2023-12-22 22:46:46 -08:00
parent 7cd4d77d15
commit cac65cbb73
Signed by: Mark
GPG Key ID: C6D63995FE72FD80
1 changed files with 72 additions and 33 deletions

View File

@ -1,4 +1,5 @@
use anyhow::Result; use anyhow::Result;
use serde::Deserialize;
use std::{collections::HashMap, fs::File, io::Read, num::NonZeroU32}; use std::{collections::HashMap, fs::File, io::Read, num::NonZeroU32};
use wgpu::BindGroupLayout; use wgpu::BindGroupLayout;
@ -7,50 +8,88 @@ use super::rawtexture::RawTexture;
pub struct TextureArray { pub struct TextureArray {
pub bind_group: wgpu::BindGroup, pub bind_group: wgpu::BindGroup,
pub bind_group_layout: BindGroupLayout, pub bind_group_layout: BindGroupLayout,
texture_dims: Vec<(u32, u32)>, textures: HashMap<String, Texture>,
texture_indices: HashMap<String, u32>, error_texture: Texture,
} }
const TEX: &[&str] = &["error", "small", "gypsum", "earth", "a0"]; #[derive(Debug, Clone, Copy)]
pub struct Texture { pub struct Texture {
pub index: u32, // Index in texture array pub index: u32, // Index in texture array
pub aspect: f32, // width / height pub aspect: f32, // width / height
pub height: f32, // Height in game units pub height: f32, // Height in game units
} }
#[derive(Deserialize)]
struct Textures {
texture: Vec<Tex>,
error: Tex,
}
#[derive(Deserialize)]
struct Tex {
name: String,
path: String,
height: f32,
}
impl Tex {
pub fn read(&self, device: &wgpu::Device, queue: &wgpu::Queue) -> Result<RawTexture> {
let p = format!("{}/{}", TextureArray::INDEX_ROOT, self.path);
let mut f = File::open(&p)?;
let mut bytes = Vec::new();
f.read_to_end(&mut bytes)?;
RawTexture::from_bytes(&device, &queue, &bytes, &self.name)
}
}
impl TextureArray { impl TextureArray {
const INDEX_PATH: &'static str = "assets/index.toml";
const INDEX_ROOT: &'static str = "assets";
pub fn get_texture(&self, name: &str) -> Texture { pub fn get_texture(&self, name: &str) -> Texture {
let index = match self.texture_indices.get(name) { match self.textures.get(name) {
Some(x) => *x, Some(x) => *x,
None => 0, // Default texture None => self.error_texture,
}; }
let dimensions = self.texture_dims[index as usize];
return Texture {
index,
height: 100.0,
aspect: dimensions.0 as f32 / dimensions.1 as f32,
};
} }
pub fn new(device: &wgpu::Device, queue: &wgpu::Queue) -> Result<Self> { pub fn new(device: &wgpu::Device, queue: &wgpu::Queue) -> Result<Self> {
let mut textures: Vec<RawTexture> = Vec::new(); // Load all textures
let mut texture_indices: HashMap<String, u32> = HashMap::new();
let mut i = 0; let (error_texture, textures, texture_data) = {
for t in TEX { let mut texture_data: Vec<RawTexture> = Vec::new();
let p = format!("assets/{t}.png"); let mut textures: HashMap<String, Texture> = HashMap::new();
let mut f = File::open(&p)?;
let mut bytes = Vec::new(); let mut texture_index_string = String::new();
f.read_to_end(&mut bytes)?; let _ = File::open(Self::INDEX_PATH)?.read_to_string(&mut texture_index_string);
textures.push(RawTexture::from_bytes(&device, &queue, &bytes, &p).unwrap()); let texture_index: Textures = toml::from_str(&texture_index_string)?;
texture_indices.insert(t.to_string(), i);
i += 1; // First texture is always error
} let raw = texture_index.error.read(device, queue)?;
let error_texture = Texture {
index: 0,
height: texture_index.error.height,
aspect: raw.dimensions.0 as f32 / raw.dimensions.1 as f32,
};
texture_data.push(raw);
// Load the rest
let mut i = 1;
for t in texture_index.texture {
let raw = t.read(device, queue)?;
let tx = Texture {
index: i,
height: t.height,
aspect: raw.dimensions.0 as f32 / raw.dimensions.1 as f32,
};
textures.insert(t.name.clone(), tx);
texture_data.push(raw);
i += 1;
}
(error_texture, textures, texture_data)
};
// One of these overall
let sampler = device.create_sampler(&wgpu::SamplerDescriptor { let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
address_mode_u: wgpu::AddressMode::ClampToEdge, address_mode_u: wgpu::AddressMode::ClampToEdge,
address_mode_v: wgpu::AddressMode::ClampToEdge, address_mode_v: wgpu::AddressMode::ClampToEdge,
@ -73,19 +112,19 @@ impl TextureArray {
view_dimension: wgpu::TextureViewDimension::D2, view_dimension: wgpu::TextureViewDimension::D2,
sample_type: wgpu::TextureSampleType::Float { filterable: true }, sample_type: wgpu::TextureSampleType::Float { filterable: true },
}, },
count: NonZeroU32::new(textures.len() as u32), count: NonZeroU32::new(texture_data.len() as u32),
}, },
// Texture sampler // Texture sampler
wgpu::BindGroupLayoutEntry { wgpu::BindGroupLayoutEntry {
binding: 1, binding: 1,
visibility: wgpu::ShaderStages::FRAGMENT, visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering), ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
count: NonZeroU32::new(textures.len() as u32), count: NonZeroU32::new(texture_data.len() as u32),
}, },
], ],
}); });
let views: Vec<&wgpu::TextureView> = textures.iter().map(|x| &x.view).collect(); let views: Vec<&wgpu::TextureView> = texture_data.iter().map(|x| &x.view).collect();
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
label: Some("texture_bind_group"), label: Some("texture_bind_group"),
layout: &bind_group_layout, layout: &bind_group_layout,
@ -105,8 +144,8 @@ impl TextureArray {
return Ok(Self { return Ok(Self {
bind_group, bind_group,
bind_group_layout, bind_group_layout,
texture_dims: textures.iter().map(|x| x.dimensions).collect(), textures,
texture_indices, error_texture,
}); });
} }
} }