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