use wgpu::{
TextureView,
TextureDescriptor,
TextureUsages,
TextureFormat,
TextureDimension,
TexelCopyTextureInfo,
TexelCopyBufferLayout,
TextureAspect,
Origin3d,
Sampler,
SamplerDescriptor,
TextureViewDescriptor,
AddressMode,
FilterMode,
MipmapFilterMode,
Device,
Queue,
Extent3d
};
use image::{
GenericImageView,
DynamicImage
};
use anyhow::*;
pub struct Texture {
pub wgpu_texture: wgpu::Texture,
pub texture_view: TextureView,
pub sampler: Sampler
}
impl Texture {
pub fn from_bytes(
device: &Device,
queue: &Queue,
bytes: &[u8],
label: &str
) -> Result<Self> {
let image: DynamicImage = image::load_from_memory(bytes)?;
return Self::from_image(device, queue, &image, Some(label));
}
pub fn from_image(
device: &Device,
queue: &Queue,
image: &DynamicImage,
label: Option<&str>
) -> Result<Self> {
let rgba = image.to_rgba8();
let dimensions: (u32, u32) = image.dimensions();
let size: Extent3d = Extent3d {
width: dimensions.0,
height: dimensions.1,
depth_or_array_layers: 1
};
let texture: wgpu::Texture = device.create_texture(&TextureDescriptor {
label,
size,
mip_level_count: 1,
sample_count: 1,
dimension: TextureDimension::D2,
format: TextureFormat::Rgba8UnormSrgb,
usage: TextureUsages::TEXTURE_BINDING | TextureUsages::COPY_DST,
view_formats: &[]
});
queue.write_texture(
TexelCopyTextureInfo {
aspect: TextureAspect::All,
texture: &texture,
mip_level: 0,
origin: Origin3d::ZERO
},
&rgba,
TexelCopyBufferLayout {
offset: 0,
bytes_per_row: Some(4 * dimensions.0),
rows_per_image: Some(dimensions.1)
},
size
);
let texture_view: TextureView = texture.create_view(&TextureViewDescriptor::default());
let sampler: Sampler = device.create_sampler(&SamplerDescriptor {
address_mode_u: AddressMode::ClampToEdge,
address_mode_v: AddressMode::ClampToEdge,
address_mode_w: AddressMode::ClampToEdge,
mag_filter: FilterMode::Nearest,
min_filter: FilterMode::Nearest,
mipmap_filter: MipmapFilterMode::Nearest,
..Default::default()
});
return Ok(Self {
wgpu_texture: texture,
texture_view,
sampler
});
}
pub(crate) fn dummy(
device: &Device,
queue: &Queue,
label: Option<&str>
) -> Result<Self> {
let color: [u8; 4] = [1.0 as u8, 1.0 as u8, 1.0 as u8, 1.0 as u8];
let size: Extent3d = Extent3d {
width: 1,
height: 1,
depth_or_array_layers: 1
};
let texture: wgpu::Texture = device.create_texture(&TextureDescriptor {
label,
size,
mip_level_count: 1,
sample_count: 1,
dimension: TextureDimension::D2,
format: TextureFormat::Rgba8UnormSrgb,
usage: TextureUsages::TEXTURE_BINDING | TextureUsages::COPY_DST,
view_formats: &[]
});
queue.write_texture(
TexelCopyTextureInfo {
aspect: TextureAspect::All,
texture: &texture,
mip_level: 0,
origin: Origin3d::ZERO,
},
&color,
TexelCopyBufferLayout {
offset: 0,
bytes_per_row: Some(4),
rows_per_image: Some(1)
},
size
);
let texture_view: TextureView = texture.create_view(&TextureViewDescriptor::default());
let sampler: Sampler = device.create_sampler(&SamplerDescriptor {
address_mode_u: AddressMode::ClampToEdge,
address_mode_v: AddressMode::ClampToEdge,
address_mode_w: AddressMode::ClampToEdge,
mag_filter: FilterMode::Linear,
min_filter: FilterMode::Linear,
mipmap_filter: MipmapFilterMode::Nearest,
..Default::default()
});
return Ok(Self {
wgpu_texture: texture,
texture_view,
sampler
});
}
}