EN-011 — render every registered probe's RT for this frame. Called from `end_frame_with_scene` BEFORE the main material pass so the probe textures are ready when materials sample them. For each probe: 1. Build the mirrored PerView (camera reflected across the probe's plane; same projection as the main camera). 2. Upload the mirrored PerView to the probe's UBO. 3. Begin a render pass against the p
(
&mut self,
encoder: &mut wgpu::CommandEncoder,
)
| 13642 | /// hardcoded foliage / particle bucket filter via the bucket |
| 13643 | /// metadata on each compiled pipeline. |
| 13644 | pub fn dispatch_planar_reflections( |
| 13645 | &mut self, |
| 13646 | encoder: &mut wgpu::CommandEncoder, |
| 13647 | ) { |
| 13648 | if self.planar_probes.iter().all(|p| p.is_none()) { return; } |
| 13649 | if self.material_system.commands.is_empty() { return; } |
| 13650 | |
| 13651 | // Build the V1 exclude set: every material linked to any |
| 13652 | // probe. The water material itself shouldn't appear in its |
| 13653 | // own reflection (it'd black-on-black self-occlude the |
| 13654 | // surface). |
| 13655 | let mut excluded: std::collections::HashSet<material_system::MaterialHandle> = |
| 13656 | std::collections::HashSet::new(); |
| 13657 | for (i, probe_link) in self.material_system.material_reflection_probe.iter().enumerate() { |
| 13658 | if probe_link.is_some() { |
| 13659 | excluded.insert((i + 1) as material_system::MaterialHandle); |
| 13660 | } |
| 13661 | } |
| 13662 | |
| 13663 | // Cache main-pass per-view inputs once outside the loop. |
| 13664 | let main_view = self.current_view_matrix; |
| 13665 | let proj = self.current_proj_matrix; |
| 13666 | let cam_pos = self.current_camera_pos; |
| 13667 | |
| 13668 | // Snapshot the existing PerView uniforms by reconstructing |
| 13669 | // the same struct material_system_begin_frame writes — we |
| 13670 | // need a fresh copy per probe to swap view/view_proj. |
| 13671 | let base_per_view = material_system::PerViewUniforms { |
| 13672 | view: main_view, |
| 13673 | proj, |
| 13674 | view_proj: self.current_vp_matrix, |
| 13675 | prev_view_proj: self.prev_vp_matrix, |
| 13676 | inv_proj: self.current_inv_proj_matrix, |
| 13677 | camera_pos: [ |
| 13678 | cam_pos[0], cam_pos[1], cam_pos[2], |
| 13679 | self.lighting_uniforms.camera_pos[3], |
| 13680 | ], |
| 13681 | camera_dir: [0.0, 0.0, -1.0, 70.0_f32.to_radians()], |
| 13682 | ambient: self.lighting_uniforms.ambient, |
| 13683 | fog: [self.fog_color[0], self.fog_color[1], self.fog_color[2], self.fog_density], |
| 13684 | sun_dir: self.lighting_uniforms.light_dir, |
| 13685 | sun_color: self.lighting_uniforms.light_color, |
| 13686 | dir_light_count: self.lighting_uniforms.dir_light_count, |
| 13687 | dir_lights: std::array::from_fn(|i| material_system::PerViewDirLight { |
| 13688 | direction: self.lighting_uniforms.dir_lights[i].direction, |
| 13689 | color: self.lighting_uniforms.dir_lights[i].color, |
| 13690 | }), |
| 13691 | point_light_count: self.lighting_uniforms.point_light_count, |
| 13692 | point_lights: std::array::from_fn(|i| material_system::PerViewPointLight { |
| 13693 | position: self.lighting_uniforms.point_lights[i].position, |
| 13694 | color: self.lighting_uniforms.point_lights[i].color, |
| 13695 | }), |
| 13696 | shadow_splits: self.lighting_uniforms.shadow_cascade_splits, |
| 13697 | shadow_view: self.lighting_uniforms.shadow_view_matrix, |
| 13698 | shadow_cascades: self.lighting_uniforms.shadow_cascade_vps, |
| 13699 | }; |
| 13700 | |
| 13701 | // Iterate probes by index — we mutate `material_system`'s |
no test coverage detected