1
2pub struct TextureCache {
3 pub textures: Vec<wgpu::Texture>,
4 pub views: Vec<wgpu::TextureView>,
5 pub default_white_view: wgpu::TextureView,
6 pub default_normal_view: wgpu::TextureView,
7 pub sampler: wgpu::Sampler,
8 _default_white: wgpu::Texture,
9 _default_normal: wgpu::Texture,
10}
11
12impl TextureCache {
13 pub fn new(device: &wgpu::Device, queue: &wgpu::Queue) -> Self {
14 let default_white = device.create_texture(&wgpu::TextureDescriptor {
16 label: Some("Default White Texture"),
17 size: wgpu::Extent3d {
18 width: 1,
19 height: 1,
20 depth_or_array_layers: 1,
21 },
22 mip_level_count: 1,
23 sample_count: 1,
24 dimension: wgpu::TextureDimension::D2,
25 format: wgpu::TextureFormat::Rgba8UnormSrgb,
26 usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
27 view_formats: &[],
28 });
29 queue.write_texture(
30 wgpu::TexelCopyTextureInfo {
31 texture: &default_white,
32 mip_level: 0,
33 origin: wgpu::Origin3d::ZERO,
34 aspect: wgpu::TextureAspect::All,
35 },
36 &[255, 255, 255, 255],
37 wgpu::TexelCopyBufferLayout {
38 offset: 0,
39 bytes_per_row: Some(4),
40 rows_per_image: Some(1),
41 },
42 wgpu::Extent3d {
43 width: 1,
44 height: 1,
45 depth_or_array_layers: 1,
46 },
47 );
48 let default_white_view = default_white.create_view(&wgpu::TextureViewDescriptor::default());
49
50 let default_normal = device.create_texture(&wgpu::TextureDescriptor {
52 label: Some("Default Normal Texture"),
53 size: wgpu::Extent3d {
54 width: 1,
55 height: 1,
56 depth_or_array_layers: 1,
57 },
58 mip_level_count: 1,
59 sample_count: 1,
60 dimension: wgpu::TextureDimension::D2,
61 format: wgpu::TextureFormat::Rgba8Unorm,
62 usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
63 view_formats: &[],
64 });
65 queue.write_texture(
66 wgpu::TexelCopyTextureInfo {
67 texture: &default_normal,
68 mip_level: 0,
69 origin: wgpu::Origin3d::ZERO,
70 aspect: wgpu::TextureAspect::All,
71 },
72 &[128, 128, 255, 255],
73 wgpu::TexelCopyBufferLayout {
74 offset: 0,
75 bytes_per_row: Some(4),
76 rows_per_image: Some(1),
77 },
78 wgpu::Extent3d {
79 width: 1,
80 height: 1,
81 depth_or_array_layers: 1,
82 },
83 );
84 let default_normal_view =
85 default_normal.create_view(&wgpu::TextureViewDescriptor::default());
86
87 let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
88 label: Some("Material Sampler"),
89 address_mode_u: wgpu::AddressMode::Repeat,
90 address_mode_v: wgpu::AddressMode::Repeat,
91 address_mode_w: wgpu::AddressMode::Repeat,
92 mag_filter: wgpu::FilterMode::Linear,
93 min_filter: wgpu::FilterMode::Linear,
94 mipmap_filter: wgpu::FilterMode::Linear,
95 lod_min_clamp: 0.0,
96 lod_max_clamp: 100.0,
97 compare: None,
98 anisotropy_clamp: 16,
99 border_color: None,
100 });
101
102 Self {
103 textures: Vec::new(),
104 views: Vec::new(),
105 default_white_view,
106 default_normal_view,
107 sampler,
108 _default_white: default_white,
109 _default_normal: default_normal,
110 }
111 }
112
113 pub fn upload_image(
115 &mut self,
116 device: &wgpu::Device,
117 queue: &wgpu::Queue,
118 image: &image::RgbaImage,
119 label: &str,
120 srgb: bool,
121 ) -> usize {
122 let (width, height) = image.dimensions();
123 let format = if srgb {
124 wgpu::TextureFormat::Rgba8UnormSrgb
125 } else {
126 wgpu::TextureFormat::Rgba8Unorm
127 };
128
129 let texture = device.create_texture(&wgpu::TextureDescriptor {
130 label: Some(label),
131 size: wgpu::Extent3d {
132 width,
133 height,
134 depth_or_array_layers: 1,
135 },
136 mip_level_count: 1,
137 sample_count: 1,
138 dimension: wgpu::TextureDimension::D2,
139 format,
140 usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
141 view_formats: &[],
142 });
143
144 queue.write_texture(
145 wgpu::TexelCopyTextureInfo {
146 texture: &texture,
147 mip_level: 0,
148 origin: wgpu::Origin3d::ZERO,
149 aspect: wgpu::TextureAspect::All,
150 },
151 image.as_raw(),
152 wgpu::TexelCopyBufferLayout {
153 offset: 0,
154 bytes_per_row: Some(width * 4),
155 rows_per_image: Some(height),
156 },
157 wgpu::Extent3d {
158 width,
159 height,
160 depth_or_array_layers: 1,
161 },
162 );
163
164 let view = texture.create_view(&wgpu::TextureViewDescriptor::default());
165 let index = self.textures.len();
166 self.textures.push(texture);
167 self.views.push(view);
168 index
169 }
170
171 pub fn get_view(&self, index: Option<usize>) -> &wgpu::TextureView {
173 match index {
174 Some(i) if i < self.views.len() => &self.views[i],
175 _ => &self.default_white_view,
176 }
177 }
178
179 pub fn get_normal_view(&self, index: Option<usize>) -> &wgpu::TextureView {
181 match index {
182 Some(i) if i < self.views.len() => &self.views[i],
183 _ => &self.default_normal_view,
184 }
185 }
186}