polyscope_render/
reflection_pass.rs1use glam::Mat4;
4use std::num::NonZeroU64;
5use wgpu::util::DeviceExt;
6
7#[repr(C)]
9#[derive(Debug, Clone, Copy, bytemuck::Pod, bytemuck::Zeroable)]
10#[allow(clippy::pub_underscore_fields)]
11pub struct ReflectionUniforms {
12 pub reflection_matrix: [[f32; 4]; 4],
13 pub intensity: f32,
14 pub ground_height: f32,
15 pub _padding: [f32; 2],
16}
17
18impl Default for ReflectionUniforms {
19 fn default() -> Self {
20 Self {
21 reflection_matrix: Mat4::IDENTITY.to_cols_array_2d(),
22 intensity: 0.25,
23 ground_height: 0.0,
24 _padding: [0.0; 2],
25 }
26 }
27}
28
29pub struct ReflectionPass {
36 uniform_buffer: wgpu::Buffer,
38 pub bind_group_layout: wgpu::BindGroupLayout,
40 bind_group: wgpu::BindGroup,
42}
43
44impl ReflectionPass {
45 #[must_use]
47 pub fn new(device: &wgpu::Device) -> Self {
48 let uniform_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
50 label: Some("Reflection Uniform Buffer"),
51 contents: bytemuck::cast_slice(&[ReflectionUniforms::default()]),
52 usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
53 });
54
55 let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
57 label: Some("Reflection Bind Group Layout"),
58 entries: &[wgpu::BindGroupLayoutEntry {
59 binding: 0,
60 visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
61 ty: wgpu::BindingType::Buffer {
62 ty: wgpu::BufferBindingType::Uniform,
63 has_dynamic_offset: false,
64 min_binding_size: NonZeroU64::new(80),
65 },
66 count: None,
67 }],
68 });
69
70 let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
72 label: Some("Reflection Bind Group"),
73 layout: &bind_group_layout,
74 entries: &[wgpu::BindGroupEntry {
75 binding: 0,
76 resource: uniform_buffer.as_entire_binding(),
77 }],
78 });
79
80 Self {
81 uniform_buffer,
82 bind_group_layout,
83 bind_group,
84 }
85 }
86
87 pub fn update_uniforms(
89 &self,
90 queue: &wgpu::Queue,
91 reflection_matrix: Mat4,
92 intensity: f32,
93 ground_height: f32,
94 ) {
95 let uniforms = ReflectionUniforms {
96 reflection_matrix: reflection_matrix.to_cols_array_2d(),
97 intensity,
98 ground_height,
99 _padding: [0.0; 2],
100 };
101 queue.write_buffer(&self.uniform_buffer, 0, bytemuck::cast_slice(&[uniforms]));
102 }
103
104 #[must_use]
106 pub fn bind_group(&self) -> &wgpu::BindGroup {
107 &self.bind_group
108 }
109
110 #[must_use]
112 pub fn bind_group_layout(&self) -> &wgpu::BindGroupLayout {
113 &self.bind_group_layout
114 }
115}
116
117#[cfg(test)]
118mod tests {
119 use super::*;
120
121 #[test]
122 fn test_reflection_uniforms_size() {
123 assert_eq!(
125 std::mem::size_of::<ReflectionUniforms>(),
126 64 + 4 + 4 + 8 );
128 }
129}