use crate::rendering::mipmap::MipGenerator;
use image::EncodableLayout;
use wgpu::{
Device, Extent3d, FilterMode, ImageCopyTexture, ImageDataLayout, Origin3d, Queue,
SamplerDescriptor, TextureDescriptor, TextureDimension, TextureFormat, TextureUsages,
};
#[derive(Debug)]
pub struct Texture {
pub texture: wgpu::Texture,
pub sampler: wgpu::Sampler,
}
impl Texture {
pub fn new(
bytes: &[u8],
label: &str,
device: &Device,
queue: &Queue,
mip_generator: &mut MipGenerator,
) -> Self {
let img = image::load_from_memory(bytes).unwrap();
let rgba = img.to_rgba8();
let max_size = rgba.width().max(rgba.height());
let log_factor = if max_size == 0 { 0 } else { max_size.ilog2() };
let optimal_mip_levels = 1 + log_factor;
let texture = device.create_texture(&TextureDescriptor {
label: Some(label),
size: Extent3d {
width: rgba.width(),
height: rgba.height(),
depth_or_array_layers: 1,
},
mip_level_count: optimal_mip_levels,
sample_count: 1,
dimension: TextureDimension::D2,
format: TextureFormat::Rgba8UnormSrgb,
usage: TextureUsages::TEXTURE_BINDING
| TextureUsages::COPY_DST
| TextureUsages::RENDER_ATTACHMENT,
view_formats: &[TextureFormat::Rgba8UnormSrgb],
});
queue.write_texture(
ImageCopyTexture {
texture: &texture,
mip_level: 0,
origin: Origin3d::ZERO,
aspect: Default::default(),
},
rgba.as_bytes(),
ImageDataLayout {
offset: 0,
bytes_per_row: Some(rgba.width() * 4),
rows_per_image: Some(rgba.height()),
},
Extent3d {
width: rgba.width(),
height: rgba.height(),
depth_or_array_layers: 1,
},
);
let sampler = device.create_sampler(&SamplerDescriptor {
label: Some("test_sampler"),
mag_filter: FilterMode::Linear,
min_filter: FilterMode::Linear,
..Default::default()
});
let tex = Self { texture, sampler };
mip_generator.generate_mips(&tex, device, queue);
tex
}
}