Skip to main content

zenthra_render/
texture.rs

1
2pub fn create_texture_bind_group(
3    device: &wgpu::Device,
4    queue: &wgpu::Queue,
5    bgl: &wgpu::BindGroupLayout,
6    bytes: &[u8],
7) -> Result<(wgpu::BindGroup, u32, u32), image::ImageError> {
8    let img = image::load_from_memory(bytes)?;
9    let rgba = img.to_rgba8();
10    let dimensions = rgba.dimensions();
11
12    let size = wgpu::Extent3d {
13        width: dimensions.0,
14        height: dimensions.1,
15        depth_or_array_layers: 1,
16    };
17
18    let texture = device.create_texture(&wgpu::TextureDescriptor {
19        label: Some("Image Texture"),
20        size,
21        mip_level_count: 1,
22        sample_count: 1,
23        dimension: wgpu::TextureDimension::D2,
24        format: wgpu::TextureFormat::Rgba8UnormSrgb,
25        usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
26        view_formats: &[],
27    });
28
29    queue.write_texture(
30        wgpu::TexelCopyTextureInfo {
31            texture: &texture,
32            mip_level: 0,
33            origin: wgpu::Origin3d::ZERO,
34            aspect: wgpu::TextureAspect::All,
35        },
36        &rgba,
37        wgpu::TexelCopyBufferLayout {
38            offset: 0,
39            bytes_per_row: Some(4 * dimensions.0),
40            rows_per_image: Some(dimensions.1),
41        },
42        size,
43    );
44
45    let view = texture.create_view(&wgpu::TextureViewDescriptor::default());
46    let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
47        address_mode_u: wgpu::AddressMode::ClampToEdge,
48        address_mode_v: wgpu::AddressMode::ClampToEdge,
49        address_mode_w: wgpu::AddressMode::ClampToEdge,
50        mag_filter: wgpu::FilterMode::Linear,
51        min_filter: wgpu::FilterMode::Linear,
52        mipmap_filter: wgpu::MipmapFilterMode::Linear,
53        ..Default::default()
54    });
55
56    let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
57        layout: bgl,
58        entries: &[
59            wgpu::BindGroupEntry {
60                binding: 0,
61                resource: wgpu::BindingResource::TextureView(&view),
62            },
63            wgpu::BindGroupEntry {
64                binding: 1,
65                resource: wgpu::BindingResource::Sampler(&sampler),
66            },
67        ],
68        label: Some("Image Bind Group"),
69    });
70
71    Ok((bind_group, dimensions.0, dimensions.1))
72}
73
74pub fn create_texture_bind_group_thumbnail(
75    device: &wgpu::Device,
76    queue: &wgpu::Queue,
77    bgl: &wgpu::BindGroupLayout,
78    bytes: &[u8],
79    max_dim: u32,
80) -> Result<(wgpu::BindGroup, u32, u32), image::ImageError> {
81    let img = image::load_from_memory(bytes)?;
82    let resized = img.thumbnail(max_dim, max_dim);
83    let rgba = resized.to_rgba8();
84    let dimensions = rgba.dimensions();
85
86    let size = wgpu::Extent3d {
87        width: dimensions.0,
88        height: dimensions.1,
89        depth_or_array_layers: 1,
90    };
91
92    let texture = device.create_texture(&wgpu::TextureDescriptor {
93        label: Some("Thumbnail Texture"),
94        size,
95        mip_level_count: 1,
96        sample_count: 1,
97        dimension: wgpu::TextureDimension::D2,
98        format: wgpu::TextureFormat::Rgba8UnormSrgb,
99        usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
100        view_formats: &[],
101    });
102
103    queue.write_texture(
104        wgpu::TexelCopyTextureInfo {
105            texture: &texture,
106            mip_level: 0,
107            origin: wgpu::Origin3d::ZERO,
108            aspect: wgpu::TextureAspect::All,
109        },
110        &rgba,
111        wgpu::TexelCopyBufferLayout {
112            offset: 0,
113            bytes_per_row: Some(4 * dimensions.0),
114            rows_per_image: Some(dimensions.1),
115        },
116        size,
117    );
118
119    let view = texture.create_view(&wgpu::TextureViewDescriptor::default());
120    let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
121        address_mode_u: wgpu::AddressMode::ClampToEdge,
122        address_mode_v: wgpu::AddressMode::ClampToEdge,
123        address_mode_w: wgpu::AddressMode::ClampToEdge,
124        mag_filter: wgpu::FilterMode::Linear,
125        min_filter: wgpu::FilterMode::Linear,
126        mipmap_filter: wgpu::MipmapFilterMode::Linear,
127        ..Default::default()
128    });
129
130    let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
131        layout: bgl,
132        entries: &[
133            wgpu::BindGroupEntry {
134                binding: 0,
135                resource: wgpu::BindingResource::TextureView(&view),
136            },
137            wgpu::BindGroupEntry {
138                binding: 1,
139                resource: wgpu::BindingResource::Sampler(&sampler),
140            },
141        ],
142        label: Some("Thumbnail Bind Group"),
143    });
144
145    Ok((bind_group, dimensions.0, dimensions.1))
146}
147