1use image::GenericImageView;
7
8pub struct Texture {
10 pub texture: wgpu::Texture,
11 pub view: wgpu::TextureView,
12 pub sampler: wgpu::Sampler,
13 pub width: u32,
14 pub height: u32,
15}
16
17impl Texture {
20 pub fn from_bytes(
21 device: &wgpu::Device,
22 queue: &wgpu::Queue,
23 bytes: &[u8],
24 label: Option<&str>,
25 ) -> Result<Self, image::ImageError> {
26 let img = image::load_from_memory(bytes)?;
27 Self::from_image(device, queue, &img, label)
28 }
29
30 pub fn from_image(
31 device: &wgpu::Device,
32 queue: &wgpu::Queue,
33 img: &image::DynamicImage,
34 label: Option<&str>,
35 ) -> Result<Self, image::ImageError> {
36 let rgba = img.to_rgba8();
37 let dimensions = img.dimensions();
38
39 let size = wgpu::Extent3d {
40 width: dimensions.0,
41 height: dimensions.1,
42 depth_or_array_layers: 1,
43 };
44
45 let texture = device.create_texture(&wgpu::TextureDescriptor {
49 label,
50 size,
51 mip_level_count: 1,
52 sample_count: 1,
53 dimension: wgpu::TextureDimension::D2,
54 format: wgpu::TextureFormat::Rgba8UnormSrgb,
55 usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
56 view_formats: &[],
57 });
58
59 queue.write_texture(
60 wgpu::TexelCopyTextureInfo {
61 texture: &texture,
62 mip_level: 0,
63 origin: wgpu::Origin3d::ZERO,
64 aspect: wgpu::TextureAspect::All,
65 },
66 &rgba,
67 wgpu::TexelCopyBufferLayout {
68 offset: 0,
69 bytes_per_row: Some(4 * dimensions.0),
70 rows_per_image: Some(dimensions.1),
71 },
72 size,
73 );
74
75 let view = texture.create_view(&wgpu::TextureViewDescriptor::default());
76 let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
77 address_mode_u: wgpu::AddressMode::ClampToEdge,
78 address_mode_v: wgpu::AddressMode::ClampToEdge,
79 mag_filter: wgpu::FilterMode::Nearest,
80 min_filter: wgpu::FilterMode::Nearest,
81 mipmap_filter: wgpu::FilterMode::Nearest,
82 ..Default::default()
83 });
84
85 Ok(Self {
86 texture,
87 view,
88 sampler,
89 width: dimensions.0,
90 height: dimensions.1,
91 })
92 }
93
94 pub fn white_pixel(device: &wgpu::Device, queue: &wgpu::Queue) -> Self {
96 use wgpu::util::DeviceExt;
97
98 let texture = device.create_texture_with_data(
99 queue,
100 &wgpu::TextureDescriptor {
101 label: Some("White Pixel Texture"),
102 size: wgpu::Extent3d {
103 width: 1,
104 height: 1,
105 depth_or_array_layers: 1,
106 },
107 mip_level_count: 1,
108 sample_count: 1,
109 dimension: wgpu::TextureDimension::D2,
110 format: wgpu::TextureFormat::Rgba8UnormSrgb,
111 usage: wgpu::TextureUsages::TEXTURE_BINDING,
112 view_formats: &[],
113 },
114 wgpu::util::TextureDataOrder::LayerMajor,
115 &[255, 255, 255, 255],
116 );
117
118 let view = texture.create_view(&wgpu::TextureViewDescriptor::default());
119 let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
120 address_mode_u: wgpu::AddressMode::ClampToEdge,
121 address_mode_v: wgpu::AddressMode::ClampToEdge,
122 mag_filter: wgpu::FilterMode::Nearest,
123 min_filter: wgpu::FilterMode::Nearest,
124 ..Default::default()
125 });
126
127 Self {
128 texture,
129 view,
130 sampler,
131 width: 1,
132 height: 1,
133 }
134 }
135}