libdqg/renderer/
texture.rs1use crate::renderer::Renderer;
2use image::GenericImageView;
3use std::path::Path;
4
5pub struct Texture {
6 pub(crate) bind_group: wgpu::BindGroup,
7 pub width: u32,
8 pub height: u32,
9}
10
11impl Texture {
12 fn new(img: image::DynamicImage, renderer: &Renderer) -> Result<Self, String> {
13 let rgba = img.to_rgba8();
14 let dimensions = img.dimensions();
15
16 let size = wgpu::Extent3d {
17 width: dimensions.0,
18 height: dimensions.1,
19 depth_or_array_layers: 1,
20 };
21
22 let texture = renderer.device.create_texture(&wgpu::TextureDescriptor {
23 label: Some("Texture"),
24 size,
25 mip_level_count: 1,
26 sample_count: 1,
27 dimension: wgpu::TextureDimension::D2,
28 format: wgpu::TextureFormat::Rgba8UnormSrgb,
29 view_formats: &[],
30 usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
31 });
32 renderer.queue.write_texture(
33 wgpu::TexelCopyTextureInfo {
35 texture: &texture,
36 mip_level: 0,
37 origin: wgpu::Origin3d::ZERO,
38 aspect: wgpu::TextureAspect::All,
39 },
40 &rgba,
42 wgpu::TexelCopyBufferLayout {
44 offset: 0,
45 bytes_per_row: Some(4 * dimensions.0),
46 rows_per_image: Some(dimensions.1),
47 },
48 size,
49 );
50 let view = texture.create_view(&wgpu::TextureViewDescriptor::default());
51
52 let bind_group = renderer.device.create_bind_group(&wgpu::BindGroupDescriptor {
53 layout: &renderer.texture_bind_group_layout,
54 entries: &[
55 wgpu::BindGroupEntry {
56 binding: 0,
57 resource: wgpu::BindingResource::TextureView(&view),
58 },
59 wgpu::BindGroupEntry {
60 binding: 1,
61 resource: wgpu::BindingResource::Sampler(&renderer.sampler),
62 },
63 ],
64 label: Some("diffuse_bind_group"),
65 });
66
67 Ok(Self {
68 bind_group,
69 width: dimensions.0,
70 height: dimensions.1
71 })
72 }
73
74 pub fn from_color(renderer: &Renderer, color: [u8; 4]) -> Result<Self, String> {
77 let img = image::RgbaImage::from_pixel(1, 1, image::Rgba(color));
78 Self::new(image::DynamicImage::ImageRgba8(img), renderer)
79 }
80
81 pub fn from_bytes(renderer: &Renderer, bytes: &[u8]) -> Result<Self, String> {
82 let img = image::load_from_memory(bytes).map_err(|e| format!("Failed to load image: {}", e))?;
83 Self::new(img, renderer)
84 }
85 pub fn from_path(renderer: &Renderer, path: impl AsRef<Path>) -> Result<Self, String> {
86 let path = crate::util::resolve_resource_path(path);
87 let img = image::open(&path)
88 .map_err(|e| format!("Failed to load image {}: {}", path.display(), e))?;
89 Self::new(img, renderer)
90 }
91}