use crate::rendering::mipmap::MipGenerator; use image::EncodableLayout; use wgpu::{ Device, Extent3d, FilterMode, ImageCopyTexture, ImageDataLayout, Origin3d, Queue, SamplerDescriptor, TextureDescriptor, TextureDimension, TextureFormat, TextureUsages, }; use super::assets::ImgData; #[derive(Debug)] pub struct Texture { pub texture: wgpu::Texture, pub sampler: wgpu::Sampler, } impl Texture { pub fn new( rgba: ImgData, label: &str, device: &Device, queue: &Queue, mip_generator: &mut MipGenerator, ) -> Self { 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.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 } }