Allocate the colour + depth textures sized to `resolution²`. Format choices match the engine's HDR pipeline so the probe texture interoperates cleanly with the rest of `material_abi`: - colour: `Rgba16Float` (`HDR_FORMAT`) so emissive geometry reflected into the probe doesn't clamp to LDR - depth: `Depth32Float` so the mirrored draws can z-test against each other without a separate downsample
(
device: &wgpu::Device,
plane_y: f32,
normal: [f32; 3],
resolution: u32,
)
| 71 | /// - depth: `Depth32Float` so the mirrored draws can z-test |
| 72 | /// against each other without a separate downsample |
| 73 | pub fn new( |
| 74 | device: &wgpu::Device, |
| 75 | plane_y: f32, |
| 76 | normal: [f32; 3], |
| 77 | resolution: u32, |
| 78 | ) -> Self { |
| 79 | // Clamp absurd inputs — a 0-px texture is illegal in wgpu |
| 80 | // and a 16k-px probe would cost more than the rest of the |
| 81 | // frame combined. 16..=4096 covers every realistic case. |
| 82 | let res = resolution.clamp(16, 4096); |
| 83 | |
| 84 | let color_rt = device.create_texture(&wgpu::TextureDescriptor { |
| 85 | label: Some("planar_reflection_color"), |
| 86 | size: wgpu::Extent3d { width: res, height: res, depth_or_array_layers: 1 }, |
| 87 | mip_level_count: 1, |
| 88 | sample_count: 1, |
| 89 | dimension: wgpu::TextureDimension::D2, |
| 90 | format: super::formats::HDR_FORMAT, |
| 91 | usage: wgpu::TextureUsages::RENDER_ATTACHMENT |
| 92 | | wgpu::TextureUsages::TEXTURE_BINDING, |
| 93 | view_formats: &[], |
| 94 | }); |
| 95 | let color_view = color_rt.create_view(&Default::default()); |
| 96 | |
| 97 | let depth_rt = device.create_texture(&wgpu::TextureDescriptor { |
| 98 | label: Some("planar_reflection_depth"), |
| 99 | size: wgpu::Extent3d { width: res, height: res, depth_or_array_layers: 1 }, |
| 100 | mip_level_count: 1, |
| 101 | sample_count: 1, |
| 102 | dimension: wgpu::TextureDimension::D2, |
| 103 | format: super::formats::DEPTH_FORMAT, |
| 104 | usage: wgpu::TextureUsages::RENDER_ATTACHMENT, |
| 105 | view_formats: &[], |
| 106 | }); |
| 107 | let depth_view = depth_rt.create_view(&Default::default()); |
| 108 | |
| 109 | // Normalise the supplied normal — caller may pass a non-unit |
| 110 | // vector; downstream math (specifically the reflection |
| 111 | // matrix below) assumes |n| == 1. |
| 112 | let n = normalise(normal); |
| 113 | |
| 114 | Self { |
| 115 | plane_y, normal: n, resolution: res, |
| 116 | color_rt, color_view, depth_rt, depth_view, |
| 117 | } |
| 118 | } |
| 119 | } |
| 120 | |
| 121 | /// Build the world-space reflection matrix for plane (n, plane_y). |
nothing calls this directly
no test coverage detected