witchcraft_renderer/types/
texture.rs1use image::GenericImageView;
2
3pub struct Texture {
5 pub texture: wgpu::Texture,
6 pub view: wgpu::TextureView,
7 pub sampler: wgpu::Sampler,
8}
9impl Texture {
10 pub fn from_bytes(
11 label: &str,
12 device: &wgpu::Device,
13 queue: &wgpu::Queue,
14 bytes: &[u8],
15 ) -> anyhow::Result<Self> {
16 let img = image::load_from_memory(bytes)?;
17 Self::from_image(label, device, queue, &img)
18 }
19
20 pub fn from_image(
21 label: &str,
22 device: &wgpu::Device,
23 queue: &wgpu::Queue,
24 img: &image::DynamicImage,
25 ) -> anyhow::Result<Self> {
26 let rgba = img.to_rgba8();
27 let dimensions = img.dimensions();
28
29 let size = wgpu::Extent3d {
30 width: dimensions.0,
31 height: dimensions.1,
32 depth_or_array_layers: 1,
33 };
34
35 let texture = device.create_texture(&wgpu::TextureDescriptor {
36 label: Some(label),
37 size,
38 mip_level_count: 1,
39 sample_count: 1,
40 dimension: wgpu::TextureDimension::D2,
41 format: wgpu::TextureFormat::Rgba8UnormSrgb,
42 usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
43 });
44
45 queue.write_texture(
46 wgpu::ImageCopyTexture {
47 aspect: wgpu::TextureAspect::All,
48 texture: &texture,
49 mip_level: 0,
50 origin: wgpu::Origin3d::ZERO,
51 },
52 &rgba,
53 wgpu::ImageDataLayout {
54 offset: 0,
55 bytes_per_row: std::num::NonZeroU32::new(4 * dimensions.0),
56 rows_per_image: std::num::NonZeroU32::new(dimensions.1),
57 },
58 size,
59 );
60
61 let view = texture.create_view(&wgpu::TextureViewDescriptor::default());
62 let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
63 address_mode_u: wgpu::AddressMode::ClampToEdge,
64 address_mode_v: wgpu::AddressMode::ClampToEdge,
65 address_mode_w: wgpu::AddressMode::ClampToEdge,
66 mag_filter: wgpu::FilterMode::Linear,
67 min_filter: wgpu::FilterMode::Nearest,
68 mipmap_filter: wgpu::FilterMode::Nearest,
69 ..Default::default()
70 });
71
72 Ok(Self {
73 texture,
74 view,
75 sampler,
76 })
77 }
78
79 pub const DEPTH_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Depth32Float;
80
81 pub fn create_depth_texture(
82 label: &str,
83 device: &wgpu::Device,
84 config: &wgpu::SurfaceConfiguration,
85 ) -> Self {
86 let size = wgpu::Extent3d {
87 width: config.width,
88 height: config.height,
89 depth_or_array_layers: 1,
90 };
91
92 let desc = wgpu::TextureDescriptor {
93 label: Some(label),
94 size,
95 mip_level_count: 1,
96 sample_count: 1,
97 dimension: wgpu::TextureDimension::D2,
98 format: Self::DEPTH_FORMAT,
99 usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::TEXTURE_BINDING,
100 };
101
102 let texture = device.create_texture(&desc);
103 let view = texture.create_view(&wgpu::TextureViewDescriptor::default());
104 let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
105 address_mode_u: wgpu::AddressMode::ClampToEdge,
106 address_mode_v: wgpu::AddressMode::ClampToEdge,
107 address_mode_w: wgpu::AddressMode::ClampToEdge,
108 mag_filter: wgpu::FilterMode::Linear,
109 min_filter: wgpu::FilterMode::Linear,
110 mipmap_filter: wgpu::FilterMode::Nearest,
111 compare: Some(wgpu::CompareFunction::LessEqual),
112 lod_min_clamp: -100.0,
113 lod_max_clamp: 100.0,
114 ..Default::default()
115 });
116
117 Self {
118 texture,
119 view,
120 sampler,
121 }
122 }
123}