Skip to main content

polyscope_render/engine/
textures.rs

1use super::RenderEngine;
2
3impl RenderEngine {
4    /// Creates the SSAO output texture (blurred result).
5    pub(crate) fn create_ssao_output_texture(&mut self) {
6        let ssao_output_texture = self.device.create_texture(&wgpu::TextureDescriptor {
7            label: Some("SSAO Output Texture"),
8            size: wgpu::Extent3d {
9                width: self.width,
10                height: self.height,
11                depth_or_array_layers: 1,
12            },
13            mip_level_count: 1,
14            sample_count: 1,
15            dimension: wgpu::TextureDimension::D2,
16            format: wgpu::TextureFormat::R8Unorm,
17            usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::TEXTURE_BINDING,
18            view_formats: &[],
19        });
20
21        let ssao_output_view =
22            ssao_output_texture.create_view(&wgpu::TextureViewDescriptor::default());
23
24        self.ssao_output_texture = Some(ssao_output_texture);
25        self.ssao_output_view = Some(ssao_output_view);
26    }
27
28    /// Creates HDR texture at specified size.
29    pub(crate) fn create_hdr_texture_with_size(&mut self, width: u32, height: u32) {
30        let hdr_texture = self.device.create_texture(&wgpu::TextureDescriptor {
31            label: Some("HDR Render Texture"),
32            size: wgpu::Extent3d {
33                width,
34                height,
35                depth_or_array_layers: 1,
36            },
37            mip_level_count: 1,
38            sample_count: 1,
39            dimension: wgpu::TextureDimension::D2,
40            format: wgpu::TextureFormat::Rgba16Float,
41            usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::TEXTURE_BINDING,
42            view_formats: &[],
43        });
44
45        let hdr_view = hdr_texture.create_view(&wgpu::TextureViewDescriptor::default());
46        self.hdr_texture = Some(hdr_texture);
47        self.hdr_view = Some(hdr_view);
48    }
49
50    /// Creates normal G-buffer texture at specified size.
51    pub fn create_normal_texture_with_size(&mut self, width: u32, height: u32) {
52        let normal_texture = self.device.create_texture(&wgpu::TextureDescriptor {
53            label: Some("Normal G-Buffer Texture"),
54            size: wgpu::Extent3d {
55                width,
56                height,
57                depth_or_array_layers: 1,
58            },
59            mip_level_count: 1,
60            sample_count: 1,
61            dimension: wgpu::TextureDimension::D2,
62            format: wgpu::TextureFormat::Rgba16Float,
63            usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::TEXTURE_BINDING,
64            view_formats: &[],
65        });
66
67        let normal_view = normal_texture.create_view(&wgpu::TextureViewDescriptor::default());
68        self.normal_texture = Some(normal_texture);
69        self.normal_view = Some(normal_view);
70    }
71
72    /// Creates SSAO output texture at specified size.
73    pub(crate) fn create_ssao_output_texture_with_size(&mut self, width: u32, height: u32) {
74        let ssao_output_texture = self.device.create_texture(&wgpu::TextureDescriptor {
75            label: Some("SSAO Output Texture"),
76            size: wgpu::Extent3d {
77                width,
78                height,
79                depth_or_array_layers: 1,
80            },
81            mip_level_count: 1,
82            sample_count: 1,
83            dimension: wgpu::TextureDimension::D2,
84            format: wgpu::TextureFormat::R8Unorm,
85            usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::TEXTURE_BINDING,
86            view_formats: &[],
87        });
88
89        let ssao_output_view =
90            ssao_output_texture.create_view(&wgpu::TextureViewDescriptor::default());
91
92        self.ssao_output_texture = Some(ssao_output_texture);
93        self.ssao_output_view = Some(ssao_output_view);
94    }
95
96    /// Creates the HDR intermediate texture for tone mapping.
97    pub(crate) fn create_hdr_texture(&mut self) {
98        let hdr_texture = self.device.create_texture(&wgpu::TextureDescriptor {
99            label: Some("HDR Texture"),
100            size: wgpu::Extent3d {
101                width: self.width,
102                height: self.height,
103                depth_or_array_layers: 1,
104            },
105            mip_level_count: 1,
106            sample_count: 1,
107            dimension: wgpu::TextureDimension::D2,
108            format: wgpu::TextureFormat::Rgba16Float, // HDR format
109            usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::TEXTURE_BINDING,
110            view_formats: &[],
111        });
112
113        let hdr_view = hdr_texture.create_view(&wgpu::TextureViewDescriptor::default());
114
115        self.hdr_texture = Some(hdr_texture);
116        self.hdr_view = Some(hdr_view);
117    }
118
119    /// Creates the normal G-buffer texture for SSAO.
120    pub(crate) fn create_normal_texture(&mut self) {
121        let normal_texture = self.device.create_texture(&wgpu::TextureDescriptor {
122            label: Some("Normal G-Buffer"),
123            size: wgpu::Extent3d {
124                width: self.width,
125                height: self.height,
126                depth_or_array_layers: 1,
127            },
128            mip_level_count: 1,
129            sample_count: 1,
130            dimension: wgpu::TextureDimension::D2,
131            format: wgpu::TextureFormat::Rgba16Float, // View-space normals (xyz) + unused (w)
132            usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::TEXTURE_BINDING,
133            view_formats: &[],
134        });
135
136        let normal_view = normal_texture.create_view(&wgpu::TextureViewDescriptor::default());
137
138        self.normal_texture = Some(normal_texture);
139        self.normal_view = Some(normal_view);
140    }
141
142    /// Creates the SSAO noise texture.
143    pub(crate) fn create_ssao_noise_texture(&mut self) {
144        use rand::Rng;
145
146        // Generate 4x4 random rotation vectors
147        let mut rng = rand::thread_rng();
148        let mut noise_data = Vec::with_capacity(4 * 4 * 4); // 4x4 pixels, RGBA8
149
150        for _ in 0..16 {
151            // Random rotation vector in tangent plane (z=0)
152            let angle: f32 = rng.gen_range(0.0..std::f32::consts::TAU);
153            let x = angle.cos();
154            let y = angle.sin();
155            // Store in [0,1] range
156            noise_data.push(((x * 0.5 + 0.5) * 255.0) as u8);
157            noise_data.push(((y * 0.5 + 0.5) * 255.0) as u8);
158            noise_data.push(0u8); // z = 0
159            noise_data.push(255u8); // w = 1
160        }
161
162        let texture = self.device.create_texture(&wgpu::TextureDescriptor {
163            label: Some("SSAO Noise Texture"),
164            size: wgpu::Extent3d {
165                width: 4,
166                height: 4,
167                depth_or_array_layers: 1,
168            },
169            mip_level_count: 1,
170            sample_count: 1,
171            dimension: wgpu::TextureDimension::D2,
172            format: wgpu::TextureFormat::Rgba8Unorm,
173            usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
174            view_formats: &[],
175        });
176
177        self.queue.write_texture(
178            wgpu::TexelCopyTextureInfo {
179                texture: &texture,
180                mip_level: 0,
181                origin: wgpu::Origin3d::ZERO,
182                aspect: wgpu::TextureAspect::All,
183            },
184            &noise_data,
185            wgpu::TexelCopyBufferLayout {
186                offset: 0,
187                bytes_per_row: Some(4 * 4),
188                rows_per_image: Some(4),
189            },
190            wgpu::Extent3d {
191                width: 4,
192                height: 4,
193                depth_or_array_layers: 1,
194            },
195        );
196
197        let view = texture.create_view(&wgpu::TextureViewDescriptor::default());
198
199        self.ssao_noise_texture = Some(texture);
200        self.ssao_noise_view = Some(view);
201    }
202}