cvkg_render_gpu/passes/
opaque3d.rs1use crate::kvasir::{ExecutionContext, KvasirNode, ResourceId};
5use crate::kvasir::nodes::PassId;
6use crate::passes::shadow::{DirectionalLight, GpuMesh3d};
7
8pub struct Opaque3dNode {
10 pub mesh_instances: Vec<GpuMesh3d>,
12 pub light: DirectionalLight,
14 pub shadow_map: ResourceId,
16}
17
18impl KvasirNode for Opaque3dNode {
19 fn label(&self) -> &'static str {
20 "Opaque3d"
21 }
22
23 fn inputs(&self) -> &[ResourceId] {
24 &[]
25 }
26
27 fn outputs(&self) -> &[ResourceId] {
28 &[]
29 }
30
31 fn pass_id(&self) -> PassId {
32 PassId::Opaque3d
33 }
34
35 fn execute(&self, ctx: &mut ExecutionContext) {
36 tracing::debug!(
37 "Opaque3dNode::execute — instances={}, shadow_map={:?}",
38 self.mesh_instances.len(),
39 self.shadow_map,
40 );
41
42 let _shadow_texture_view = match ctx.registry.get_texture_view(self.shadow_map) {
44 Some(v) => v,
45 None => {
46 tracing::warn!(
47 "Opaque3dNode: shadow map texture view not found — \
48 proceeding without shadows",
49 );
50 return;
51 }
52 };
53
54 let scene_view = match ctx
56 .registry
57 .get_texture_view(crate::kvasir::nodes::RES_SCENE)
58 {
59 Some(v) => v,
60 None => {
61 tracing::error!("Opaque3dNode: missing scene color target");
62 return;
63 }
64 };
65 let depth_view = ctx.depth_view;
66
67 let bg = [0.02f32, 0.02, 0.05, 1.0];
69
70 let mut pass = ctx.encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
72 label: Some("Opaque3d Pass (PBR + Shadows)"),
73 color_attachments: &[Some(wgpu::RenderPassColorAttachment {
74 view: &scene_view,
75 resolve_target: None,
76 ops: wgpu::Operations {
77 load: wgpu::LoadOp::Clear(wgpu::Color {
78 r: bg[0] as f64,
79 g: bg[1] as f64,
80 b: bg[2] as f64,
81 a: bg[3] as f64,
82 }),
83 store: wgpu::StoreOp::Store,
84 },
85 depth_slice: None,
86 })],
87 depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment {
88 view: depth_view,
89 depth_ops: Some(wgpu::Operations {
90 load: wgpu::LoadOp::Load,
91 store: wgpu::StoreOp::Store,
92 }),
93 stencil_ops: None,
94 }),
95 timestamp_writes: None,
96 occlusion_query_set: None,
97 multiview_mask: None,
98 });
99
100 for mesh in self.mesh_instances.iter() {
102 pass.set_vertex_buffer(0, mesh.vertex_buffer.slice(..));
103 pass.set_index_buffer(mesh.index_buffer.slice(..), wgpu::IndexFormat::Uint32);
104 pass.draw_indexed(0..mesh.index_count, 0, 0..1);
105 }
106 }
107}