Skip to main content

cvkg_render_gpu/passes/
gbuffer.rs

1//! G-Buffer pass - Renders scene geometry to intermediate buffers.
2//! Used for deferred lighting, SSAO, and motion vector computation.
3
4use crate::kvasir::nodes::PassId;
5use crate::kvasir::{ExecutionContext, KvasirNode, ResourceId};
6
7/// Resource IDs for the G-Buffer textures.
8pub const RES_GBUFFER_ALBEDO: ResourceId = ResourceId(400);
9pub const RES_GBUFFER_NORMAL: ResourceId = ResourceId(401);
10pub const RES_GBUFFER_MOTION: ResourceId = ResourceId(402);
11
12/// G-Buffer rendering node.
13pub struct GBufferNode {
14    /// Opaque mesh instances to draw.
15    pub mesh_instances: Vec<crate::passes::shadow::GpuMesh3d>,
16}
17
18impl KvasirNode for GBufferNode {
19    fn label(&self) -> &'static str {
20        "GBufferPass"
21    }
22
23    fn inputs(&self) -> &[ResourceId] {
24        &[]
25    }
26
27    fn outputs(&self) -> &[ResourceId] {
28        &[RES_GBUFFER_ALBEDO, RES_GBUFFER_NORMAL, RES_GBUFFER_MOTION]
29    }
30
31    fn pass_id(&self) -> PassId {
32        PassId::Geometry
33    }
34
35    fn execute(&self, ctx: &mut ExecutionContext) {
36        tracing::debug!(
37            "GBufferNode::execute - Rendering {} instances into G-Buffer",
38            self.mesh_instances.len()
39        );
40
41        let albedo_view = match ctx.registry.get_texture_view(RES_GBUFFER_ALBEDO) {
42            Some(v) => v,
43            None => return,
44        };
45        let normal_view = match ctx.registry.get_texture_view(RES_GBUFFER_NORMAL) {
46            Some(v) => v,
47            None => return,
48        };
49        let motion_view = match ctx.registry.get_texture_view(RES_GBUFFER_MOTION) {
50            Some(v) => v,
51            None => return,
52        };
53
54        // Create a render pass rendering to three attachments + depth
55        let mut _pass = ctx.encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
56            label: Some("G-Buffer Pass"),
57            color_attachments: &[
58                Some(wgpu::RenderPassColorAttachment {
59                    view: &albedo_view,
60                    resolve_target: None,
61                    ops: wgpu::Operations {
62                        load: wgpu::LoadOp::Clear(wgpu::Color::BLACK),
63                        store: wgpu::StoreOp::Store,
64                    },
65                    depth_slice: None,
66                }),
67                Some(wgpu::RenderPassColorAttachment {
68                    view: &normal_view,
69                    resolve_target: None,
70                    ops: wgpu::Operations {
71                        load: wgpu::LoadOp::Clear(wgpu::Color::BLACK),
72                        store: wgpu::StoreOp::Store,
73                    },
74                    depth_slice: None,
75                }),
76                Some(wgpu::RenderPassColorAttachment {
77                    view: &motion_view,
78                    resolve_target: None,
79                    ops: wgpu::Operations {
80                        load: wgpu::LoadOp::Clear(wgpu::Color::BLACK),
81                        store: wgpu::StoreOp::Store,
82                    },
83                    depth_slice: None,
84                }),
85            ],
86            depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment {
87                view: ctx.depth_view,
88                depth_ops: Some(wgpu::Operations {
89                    load: wgpu::LoadOp::Clear(0.0),
90                    store: wgpu::StoreOp::Store,
91                }),
92                stencil_ops: None,
93            }),
94            timestamp_writes: None,
95            occlusion_query_set: None,
96            multiview_mask: None,
97        });
98
99        // Loop and draw instances with normal/position/uv shaders
100    }
101}