summaryrefslogtreecommitdiff
path: root/cnn_v3/tools/shaders.js
diff options
context:
space:
mode:
authorskal <pascal.massimino@gmail.com>2026-03-22 16:21:25 +0100
committerskal <pascal.massimino@gmail.com>2026-03-22 16:21:25 +0100
commit159ca2ca19345515cdfebed9fd88646730492cd2 (patch)
tree75f350e4e89003b914e0645e47118f88992d66c0 /cnn_v3/tools/shaders.js
parentc8d5c02bae82e506f6bb507c9ed07aeba3a1bb87 (diff)
feat(cnn_v3): add G-buffer visualizer + web sample loader (Phase 7)
C++ GBufViewEffect: renders all 20 feature channels from feat_tex0/feat_tex1 in a 4×5 tiled grid. Custom BGL with WGPUTextureSampleType_Uint; bind group rebuilt per frame via wgpuRenderPipelineGetBindGroupLayout. Web tool: "Load sample directory" button — webkitdirectory picker, FULL_PACK_SHADER compute (matches gbuf_pack.wgsl packing), runFromFeat() skips photo-pack step, computePSNR() readback + comparison vs target.png side-by-side. 36/36 tests pass. Docs updated: HOWTO.md §9, README, PROJECT_CONTEXT, TODO, COMPLETED. handoff(Gemini): CNN v3 Phase 7 done. Next: run train_cnn_v3.py (see HOWTO §3).
Diffstat (limited to 'cnn_v3/tools/shaders.js')
-rw-r--r--cnn_v3/tools/shaders.js48
1 files changed, 48 insertions, 0 deletions
diff --git a/cnn_v3/tools/shaders.js b/cnn_v3/tools/shaders.js
index c3e994d..d5b1fb4 100644
--- a/cnn_v3/tools/shaders.js
+++ b/cnn_v3/tools/shaders.js
@@ -250,3 +250,51 @@ const VIZ_U32=`
var v=array<f32,8>(a.x,a.y,b.x,b.y,c.x,c.y,d.x,d.y);
let x=clamp(v[min(ch,7u)],0.,1.); return vec4f(x,x,x,1.);
}`;
+
+// Full G-buffer pack: assembles feat_tex0/feat_tex1 from individual G-buffer images.
+// Bindings: albedo(0) normal(1) depth(2) matid(3) shadow(4) transp(5) sampler(6) f0(7) f1(8)
+// All source textures are rgba8unorm (browser-loaded images, R channel for depth/matid/shadow/transp).
+// Matches gbuf_pack.wgsl packing exactly so the CNN sees the same layout.
+const FULL_PACK_SHADER=`
+@group(0) @binding(0) var albedo: texture_2d<f32>;
+@group(0) @binding(1) var normal: texture_2d<f32>;
+@group(0) @binding(2) var depth: texture_2d<f32>;
+@group(0) @binding(3) var matid: texture_2d<f32>;
+@group(0) @binding(4) var shadow: texture_2d<f32>;
+@group(0) @binding(5) var transp: texture_2d<f32>;
+@group(0) @binding(6) var smp: sampler;
+@group(0) @binding(7) var f0: texture_storage_2d<rgba32uint,write>;
+@group(0) @binding(8) var f1: texture_storage_2d<rgba32uint,write>;
+fn ld(c:vec2i,d:vec2i)->f32{return textureLoad(depth,clamp(c,vec2i(0),d-vec2i(1)),0).r;}
+fn b2(tl:vec2i,d:vec2i)->vec3f{
+ var s=vec3f(0.);
+ for(var y:i32=0;y<2;y++){for(var x:i32=0;x<2;x++){s+=textureLoad(albedo,clamp(tl+vec2i(x,y),vec2i(0),d-vec2i(1)),0).rgb;}}
+ return s*.25;}
+fn b4(tl:vec2i,d:vec2i)->vec3f{
+ var s=vec3f(0.);
+ for(var y:i32=0;y<4;y++){for(var x:i32=0;x<4;x++){s+=textureLoad(albedo,clamp(tl+vec2i(x,y),vec2i(0),d-vec2i(1)),0).rgb;}}
+ return s*(1./16.);}
+@compute @workgroup_size(8,8)
+fn main(@builtin(global_invocation_id) id:vec3u){
+ let c=vec2i(id.xy); let d=vec2i(textureDimensions(albedo));
+ if(c.x>=d.x||c.y>=d.y){return;}
+ let alb=textureLoad(albedo,c,0).rgb;
+ let nrm=textureLoad(normal,c,0).rg;
+ let oct=nrm*2.-vec2f(1.); // [0,1] -> [-1,1]
+ let dv=ld(c,d);
+ let dzdx=(ld(c+vec2i(1,0),d)-ld(c-vec2i(1,0),d))*.5;
+ let dzdy=(ld(c+vec2i(0,1),d)-ld(c-vec2i(0,1),d))*.5;
+ textureStore(f0,c,vec4u(
+ pack2x16float(alb.rg),
+ pack2x16float(vec2f(alb.b,oct.x)),
+ pack2x16float(vec2f(oct.y,dv)),
+ pack2x16float(vec2f(dzdx,dzdy))));
+ let mid=textureLoad(matid,c,0).r;
+ let shd=textureLoad(shadow,c,0).r;
+ let trp=textureLoad(transp,c,0).r;
+ let m1=b2(c-vec2i(0),d); let m2=b4(c-vec2i(1),d);
+ textureStore(f1,c,vec4u(
+ pack4x8unorm(vec4f(mid,0.,0.,0.)),
+ pack4x8unorm(vec4f(m1.r,m1.g,m1.b,m2.r)),
+ pack4x8unorm(vec4f(m2.g,m2.b,shd,trp)),
+ 0u));}`;