// G-buffer rasterization shader for CNN v3 // Pass 1: Proxy geometry → MRT (albedo rgba16float, normal_mat rgba16float, depth32) // Uses GlobalUniforms, ObjectData, ObjectsBuffer from common_uniforms. #include "common_uniforms" #include "math/normal" @group(0) @binding(0) var globals: GlobalUniforms; @group(0) @binding(1) var object_data: ObjectsBuffer; struct VertexOutput { @builtin(position) position: vec4f, @location(0) world_pos: vec3f, @location(1) world_normal: vec3f, @location(2) color: vec4f, @location(3) @interpolate(flat) instance_index: u32, } @vertex fn vs_main( @builtin(vertex_index) vertex_index: u32, @builtin(instance_index) instance_index: u32 ) -> VertexOutput { // Proxy box vertices (same as renderer_3d.wgsl) var pos = array( vec3f(-1.0, -1.0, 1.0), vec3f( 1.0, -1.0, 1.0), vec3f( 1.0, 1.0, 1.0), vec3f(-1.0, -1.0, 1.0), vec3f( 1.0, 1.0, 1.0), vec3f(-1.0, 1.0, 1.0), vec3f(-1.0, -1.0, -1.0), vec3f(-1.0, 1.0, -1.0), vec3f( 1.0, 1.0, -1.0), vec3f(-1.0, -1.0, -1.0), vec3f( 1.0, 1.0, -1.0), vec3f( 1.0, -1.0, -1.0), vec3f(-1.0, 1.0, -1.0), vec3f(-1.0, 1.0, 1.0), vec3f( 1.0, 1.0, 1.0), vec3f(-1.0, 1.0, -1.0), vec3f( 1.0, 1.0, 1.0), vec3f( 1.0, 1.0, -1.0), vec3f(-1.0, -1.0, -1.0), vec3f( 1.0, -1.0, -1.0), vec3f( 1.0, -1.0, 1.0), vec3f(-1.0, -1.0, -1.0), vec3f( 1.0, -1.0, 1.0), vec3f(-1.0, -1.0, 1.0), vec3f( 1.0, -1.0, -1.0), vec3f( 1.0, 1.0, -1.0), vec3f( 1.0, 1.0, 1.0), vec3f( 1.0, -1.0, -1.0), vec3f( 1.0, 1.0, 1.0), vec3f( 1.0, -1.0, 1.0), vec3f(-1.0, -1.0, -1.0), vec3f(-1.0, -1.0, 1.0), vec3f(-1.0, 1.0, 1.0), vec3f(-1.0, -1.0, -1.0), vec3f(-1.0, 1.0, 1.0), vec3f(-1.0, 1.0, -1.0) ); // Proxy face normals (one per 2 triangles = 6 faces × 6 verts = 36) var nrm = array( vec3f(0,0,1), vec3f(0,0,1), vec3f(0,0,1), vec3f(0,0,1), vec3f(0,0,1), vec3f(0,0,1), vec3f(0,0,-1), vec3f(0,0,-1), vec3f(0,0,-1), vec3f(0,0,-1), vec3f(0,0,-1), vec3f(0,0,-1), vec3f(0,1,0), vec3f(0,1,0), vec3f(0,1,0), vec3f(0,1,0), vec3f(0,1,0), vec3f(0,1,0), vec3f(0,-1,0), vec3f(0,-1,0), vec3f(0,-1,0), vec3f(0,-1,0), vec3f(0,-1,0), vec3f(0,-1,0), vec3f(1,0,0), vec3f(1,0,0), vec3f(1,0,0), vec3f(1,0,0), vec3f(1,0,0), vec3f(1,0,0), vec3f(-1,0,0), vec3f(-1,0,0), vec3f(-1,0,0), vec3f(-1,0,0), vec3f(-1,0,0), vec3f(-1,0,0) ); let obj = object_data.objects[instance_index]; let p = pos[vertex_index]; let n = nrm[vertex_index]; let world_pos = obj.model * vec4f(p, 1.0); let clip_pos = globals.view_proj * world_pos; // Transform normal: use model matrix (correct for uniform scale + rotation). let world_normal = normalize((obj.model * vec4f(n, 0.0)).xyz); var out: VertexOutput; out.position = clip_pos; out.world_pos = world_pos.xyz; out.world_normal = world_normal; out.color = obj.color; out.instance_index = instance_index; return out; } struct GBufOutput { @location(0) albedo: vec4f, // rgba16float: material color @location(1) normal_mat: vec4f, // rgba16float: oct-normal XY in RG, mat_id/255 in B } @fragment fn fs_main(in: VertexOutput) -> GBufOutput { let obj = object_data.objects[in.instance_index]; let mat_id = f32(in.instance_index) / 255.0; // Oct-encode world normal, remap [-1,1] → [0,1] for storage let oct = oct_encode_unorm(normalize(in.world_normal)); var out: GBufOutput; out.albedo = vec4f(in.color.rgb, 1.0); out.normal_mat = vec4f(oct.x, oct.y, mat_id, 0.0); return out; }