Files
rust-engine/src/vulkan/dds.rs
2021-10-24 18:57:46 +02:00

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
}
}