rend3_routine/
uniforms.rs

1//! Helpers for building the per-camera uniform data used for cameras and
2//! shadows.
3
4use glam::{Mat4, Vec4};
5use rend3::{
6    graph::{DataHandle, RenderGraph},
7    managers::CameraManager,
8    util::{bind_merge::BindGroupBuilder, frustum::ShaderFrustum},
9};
10use wgpu::{
11    util::{BufferInitDescriptor, DeviceExt},
12    BindGroup, BufferUsages,
13};
14
15use crate::common::{Samplers, WholeFrameInterfaces};
16
17/// The actual structure passed to the shader.
18#[derive(Debug, Copy, Clone)]
19#[repr(C, align(16))]
20pub struct FrameUniforms {
21    pub view: Mat4,
22    pub view_proj: Mat4,
23    pub origin_view_proj: Mat4,
24    pub inv_view: Mat4,
25    pub inv_view_proj: Mat4,
26    pub inv_origin_view_proj: Mat4,
27    pub frustum: ShaderFrustum,
28    pub ambient: Vec4,
29}
30impl FrameUniforms {
31    /// Use the given camera to generate these uniforms.
32    pub fn new(camera: &CameraManager, ambient: Vec4) -> Self {
33        profiling::scope!("create uniforms");
34
35        let view = camera.view();
36        let view_proj = camera.view_proj();
37        let origin_view_proj = camera.origin_view_proj();
38
39        Self {
40            view,
41            view_proj,
42            origin_view_proj,
43            inv_view: view.inverse(),
44            inv_view_proj: view_proj.inverse(),
45            inv_origin_view_proj: origin_view_proj.inverse(),
46            frustum: ShaderFrustum::from_matrix(camera.proj()),
47            ambient,
48        }
49    }
50}
51
52unsafe impl bytemuck::Zeroable for FrameUniforms {}
53unsafe impl bytemuck::Pod for FrameUniforms {}
54
55/// Add the creation of these uniforms to the graph.
56pub fn add_to_graph<'node>(
57    graph: &mut RenderGraph<'node>,
58    shadow_uniform_bg: DataHandle<BindGroup>,
59    forward_uniform_bg: DataHandle<BindGroup>,
60    interfaces: &'node WholeFrameInterfaces,
61    samplers: &'node Samplers,
62    ambient: Vec4,
63) {
64    let mut builder = graph.add_node("build uniform data");
65    let shadow_handle = builder.add_data_output(shadow_uniform_bg);
66    let forward_handle = builder.add_data_output(forward_uniform_bg);
67    builder.build(move |_pt, renderer, _encoder_or_pass, _temps, _ready, graph_data| {
68        let mut bgb = BindGroupBuilder::new();
69
70        samplers.add_to_bg(&mut bgb);
71
72        let uniforms = FrameUniforms::new(graph_data.camera_manager, ambient);
73        let uniform_buffer = renderer.device.create_buffer_init(&BufferInitDescriptor {
74            label: Some("frame uniform"),
75            contents: bytemuck::bytes_of(&uniforms),
76            usage: BufferUsages::UNIFORM,
77        });
78
79        bgb.append_buffer(&uniform_buffer);
80
81        let shadow_uniform_bg = bgb.build(
82            &renderer.device,
83            Some("shadow uniform bg"),
84            &interfaces.depth_uniform_bgl,
85        );
86
87        graph_data.directional_light_manager.add_to_bg(&mut bgb);
88
89        let forward_uniform_bg = bgb.build(
90            &renderer.device,
91            Some("forward uniform bg"),
92            &interfaces.forward_uniform_bgl,
93        );
94
95        graph_data.set_data(shadow_handle, Some(shadow_uniform_bg));
96        graph_data.set_data(forward_handle, Some(forward_uniform_bg));
97    })
98}