47 lines
1.9 KiB
Rust
47 lines
1.9 KiB
Rust
use std::{convert::TryInto, io::Read};
|
|
|
|
use vulkano::{format::Format, sampler::{Filter, SamplerAddressMode}};
|
|
|
|
use super::{Texture, VulkanRenderer};
|
|
|
|
pub fn upload_texture_from_file(path: &str, renderer: &mut VulkanRenderer) -> Result<Texture, Box<dyn std::error::Error>> {
|
|
// Load file
|
|
let mut tex_file = std::fs::File::open(path)?;
|
|
let mut tex_bytes: Vec<u8> = vec![];
|
|
tex_file.read_to_end(&mut tex_bytes)?;
|
|
|
|
// Parse DDS
|
|
let tex_height = u32::from_ne_bytes(tex_bytes[12..16].try_into()?);
|
|
let tex_width = u32::from_ne_bytes(tex_bytes[16..20].try_into()?);
|
|
let tex_byte_count = u32::from_ne_bytes(tex_bytes[20..24].try_into()?);
|
|
let pixel_format_flags = u32::from_ne_bytes(tex_bytes[80..84].try_into()?);
|
|
let pixel_format_name: [u8; 4] = tex_bytes[84..88].try_into()?;
|
|
let is_dxt1 = pixel_format_name == [0x44, 0x58, 0x54, 0x31]; // [D,X,T,1]
|
|
let is_dx10 = pixel_format_name == [0x44, 0x58, 0x31, 0x30]; // [D,X,1,0]
|
|
|
|
assert!(pixel_format_flags == 0x00000004);
|
|
assert!(is_dxt1 || is_dx10);
|
|
|
|
println!("Texture width: {}, height: {}, bytes: {}", tex_width, tex_height, tex_byte_count);
|
|
|
|
let texture = if is_dxt1 {
|
|
renderer.upload_texture(&tex_bytes[128..], tex_width, tex_height, Format::BC1_RGB_UNORM_BLOCK, Filter::Linear, SamplerAddressMode::Repeat, renderer.device.clone())
|
|
} else if is_dx10 {
|
|
let dxgi_type = u32::from_ne_bytes(tex_bytes[128..132].try_into()?);
|
|
assert!(dxgi_type == 83); // BC5 Unorm Typeless
|
|
|
|
renderer.upload_texture(&tex_bytes[128+20..], tex_width, tex_height, Format::BC5_UNORM_BLOCK, Filter::Linear, SamplerAddressMode::Repeat, renderer.device.clone())
|
|
} else {
|
|
panic!("Unknown texture type!");
|
|
};
|
|
|
|
Ok(texture)
|
|
}
|
|
|
|
pub fn get_block_size(format: Format) -> Option<u32> {
|
|
match format {
|
|
Format::BC1_RGB_UNORM_BLOCK => Some(8),
|
|
Format::BC5_UNORM_BLOCK => Some(16),
|
|
_ => None
|
|
}
|
|
} |