summaryrefslogtreecommitdiff
path: root/cnn_v3/src/gbuffer_effect.cc
AgeCommit message (Collapse)Author
14 hoursfix(cnn_v3_debug): add CNNv3Effect to debug sequence for prev.r/g/b temporal ↵skal
feedback timeline.seq is the canonical source — timeline.cc was wrongly hand-edited. Add CNNv3Effect + cnn_out (gbuf_albedo) node to cnn_v3_debug sequence so wire_dag() can wire GBufferEffect.cnn_output_node_ correctly. Also fix node_prev_tex_ NodeType: F16X8 (Rgba16Float+CopyDst) to match CNNv3Effect output format (GBUF_ALBEDO = Rgba16Float). Regenerated timeline.cc via: python3 tools/seq_compiler.py workspaces/main/timeline.seq Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
14 hoursfeat(gbuffer): wire_dag() + find_downstream_output() for temporal feedbackskal
- Add Effect::wire_dag() virtual (called from init_effect_nodes after full DAG built) - Add Effect::find_downstream_output() protected helper (first downstream consumer output) - GBufferEffect::wire_dag() auto-sets cnn_output_node_ via find_downstream_output, guarding against sink (external view, null texture) - GBufferEffect::post_render() null-checks src texture before CopyTextureToTexture - Tests: find_downstream_output cases + wire_dag integration in test_effect_base - Doc: SEQUENCE.md updated with wire_dag pattern, helper contract, and sink guard Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
14 hoursfeat(cnn_v3): GBufferEffect temporal feedback via post_render()skal
- Add Effect::post_render() virtual hook, called after all effects in the sequence have rendered each frame. Default is no-op. - Sequence::render_effects() runs a second pass invoking post_render() on all DAG nodes after the render pass completes. - GBufferEffect: declare internal node_prev_tex_ (U8X4_NORM) for persistent prev-frame CNN output. post_render() copies cnn_output_node_ → node_prev_tex_ via CopyTextureToTexture. render() binds node_prev_tex_ as prev_cnn (binding 6) — zero on frame 0 (matches training convention). - Expose set_cnn_output_node(name) API; call once at setup. - Drop brittle ping-pong / input_nodes_[0] fallback. - Update doc/SEQUENCE.md: post_render() semantics, frame execution order, temporal feedback canonical pattern, node types table with G-buffer types. - Update cnn_v3/docs/HOWTO.md: temporal feedback wiring section. 36/36 tests passing. handoff(Gemini): prev.rgb temporal feedback now correct and generic. Set set_cnn_output_node("sink") (or CNN output node name) once at setup.
22 hourswip(cnn_v3): shadow→dif intermediate + scene tweaks + migration planskal
- gbuf_shadow.wgsl: normal bias 0.05→0.02 - gbuf_pack.wgsl: compute dif=diffuse*shadow, drop shadow from t1.z, store dif in t1.w (INTERMEDIATE — incorrect packing, see migration plan) - gbuf_deferred.wgsl: read dif from t1.w.x (matches intermediate packing) - gbuf_view.wgsl: expand to 4×6 grid, show dif.r/g/b in row 5 (INTERMEDIATE — to be reverted to 4×5 with ch18=dif) - gbuffer_effect.cc: add small hovering sphere (r=0.6) above scene; swap cube/sphere positions; both spheres pulsate - docs/GBUF_DIF_MIGRATION.md: full migration plan with checklist handoff(Claude): intermediate commit — GBUF_DIF_MIGRATION.md §Current State describes what is wrong and the full implementation checklist (5 steps).
22 hoursrefactor(cnn_v3): simplify sphere SDF in shadow pass, remove per-frame allocskal
gbuf_shadow.wgsl — dfWithID(): - Sphere: replace inv_model local-space transform with direct world-space formula (length(p - center) - radius). Exact, no matrix multiply, no floating-point error from matrix inversion that can corrupt soft-shadow penumbra over 64 march steps. - lp/scale now computed only inside the cases that need them (box/torus/plane) instead of eagerly for every object. gbuffer_effect.cc — upload_scene_data(): - Replace per-frame std::vector<GBufObjectData> heap allocation with a file-static staging buffer s_obj_staging[256]: zero alloc per frame. handoff(Gemini): sphere SDF now exact; shadow march should be cleaner.
23 hoursfix(cnn_v3): shadow pass — 5 bugs fixed, labels in gbuf_viewskal
1. Camera Y-inversion: proj.m[5] = -proj.m[5] in upload_scene_data + WGPUFrontFace_CCW on raster pipeline. 2. Shadow formula: replace shadowWithStoredDistance with 64-step IQ soft shadow (8*d/t, unbounded). 3. Local→world SDF scale: d *= length(obj.model[0].xyz). 4. Shadow bias: use rasterized normal from normal_mat_tex (binding 4) instead of light direction — fixes terminator self-shadow on spheres. 5. ShaderComposer: GBufViewEffect now resolves #include via ShaderComposer::Get().Compose(). Also: per-tile channel labels in gbuf_view.wgsl via debug_str. Scene simplified to 1 cube + 1 sphere for debugging (restore TODO). Scale propagation for pulsating sphere confirmed correct end-to-end. handoff(Gemini): shadow validated. Next: restore full scene in GBufferEffect::set_scene() (20 cubes + 4 spheres, 2 lights), then run training pass per cnn_v3/docs/HOWTO.md §3.
26 hoursfix(cnn_v3): frontFace_CW for raster pipeline + sphere impostor in gbuf_rasterskal
- Missing WGPUFrontFace_CW (Y-flipped perspective) caused back faces to render instead of front faces → cubes appeared inside-out. - Sphere objects now use ray-sphere impostor in fs_main: correct silhouette, smooth normal from hit point, and reprojected clip-space depth.
26 hoursfix(cnn_v3): call set_scene() in constructor + orbiting cameraskal
- GBufferEffect::render() was a no-op (scene_ready_=false) because set_scene() was never called from the timeline sequence constructor. Fixed by calling set_scene() at the end of the constructor. - Camera now orbits the scene at 0.3 rad/s (R=6, y=2.5). handoff(Gemini): cnn_v3_test sequence now renders G-buffer + GBufViewEffect with animated orbiting camera.
26 hoursrefactor(cnn_v3): GBufferEffect cleanupskal
Remove dead code and reduce duplication: - drop create_bilinear_sampler() (never called) - drop update_pack_bind_group() stub and pack_bind_group_ member - drop node_feat0_/node_feat1_; use output_nodes_[0/1] directly - Compose({}, src) consistently for all three pipelines - extract clear_r8_node() helper to replace two identical 10-line blocks No behavior change. 36/36 tests pass.
27 hoursfeat(cnn_v3): GBufferEffect Pass 2 — SDF shadow raymarchingskal
Implements gbuf_shadow.wgsl: fullscreen render pass that reads depth from Pass 1, reconstructs world-space positions, evaluates a proxy-box SDF for each object (via inv_model), computes soft shadows for both directional lights using shadowWithStoredDistance(), and writes shadow factor to the RGBA8Unorm node_shadow_ target consumed by gbuf_pack.wgsl. Bind layout: B0=GlobalUniforms, B1=ObjectsBuffer (storage-read), B2=texture_depth_2d, B3=GBufLightsUniforms. Sky fragments (depth=1.0) are output as 1.0 (fully lit). Falls back to clear(1.0) if pipeline is not ready. 36/36 tests pass. handoff(Gemini): Pass 2 done. Pass 3 (transparency) still TODO. Phase 4 (type-aware SDF) optional after visual validation.
27 hoursfeat(cnn_v3): GBufferEffect internal scene + GBufViewEffect debug wiringskal
GBufferEffect: - set_scene() now owns Scene/Camera internally; no external pointers needed - 20 randomly rotating cubes (xorshift32 seed, axis-angle animation) - 4 pumping spheres (radius = base_r * (1 + audio_intensity * 0.8)) - Camera at (0,2.5,6) looking at origin; aspect updated per-frame - GBufLightsUniforms: 2 directional lights (warm key + cool fill) - object_type written to ObjectData.params.x (ready for SDF shadow) - shadow/transp nodes cleared via zero-draw render passes (placeholder) - bilinear sampler cached via create_linear_sampler() / sampler_.get() - dead placeholder textures removed GBufViewEffect: - gbuf_view.wgsl: all channels now fully grayscale (removed color tint) - seq_compiler.py: GBufViewEffect added to CLASS_TO_HEADER - timeline.seq: cnn_v3_test uses GBufViewEffect -> sink for debug view Docs: HOWTO.md §1 updated with set_scene() description + §1b implementation plan for Pass 2 SDF shadow (shader spec, bind layout, C++ additions) handoff(Gemini): GBufferEffect has internal scene, 36/36 tests green. Next: implement Pass 2 shadow (gbuf_shadow.wgsl) per §1b plan in HOWTO.md.
4 daysfeat(cnn_v3): Phase 1 complete - GBufferEffect integrated + HOWTO playbookskal
- Wire GBufferEffect into demo build: assets.txt, DemoSourceLists.cmake, demo_effects.h, shaders.h/cc. ShaderComposer::Compose() applied to gbuf_raster.wgsl (resolves #include "common_uniforms"). - Add GBufferEffect construction test. 35/35 passing. - Write cnn_v3/docs/HOWTO.md: G-buffer wiring, training data prep, training plan, per-pixel validation workflow, phase status table, troubleshooting guide. - Add project hooks: remind to update HOWTO.md on cnn_v3/ edits; warn on direct str_view(*_wgsl) usage bypassing ShaderComposer. - Update PROJECT_CONTEXT.md and TODO.md: Phase 1 done, Phase 3 (WGSL U-Net shaders) is next active. handoff(Gemini): CNN v3 Phase 3 is next - WGSL enc/dec/bottleneck/FiLM shaders in cnn_v3/shaders/. See cnn_v3/docs/CNN_V3.md Architecture section and cnn_v3/docs/HOWTO.md section 3 for spec. GBufferEffect outputs feat_tex0 + feat_tex1 (rgba32uint, 20ch, 32 bytes/pixel). C++ CNNv3Effect (Phase 4) takes those as input nodes.
4 daysfeat(cnn_v3): G-buffer phase 1 + training infrastructureskal
G-buffer (Phase 1): - Add NodeTypes GBUF_ALBEDO/DEPTH32/R8/RGBA32UINT to NodeRegistry - GBufferEffect: MRT raster pass (albedo+normal_mat+depth) + pack compute - Shaders: gbuf_raster.wgsl (MRT), gbuf_pack.wgsl (feature packing, 32B/px) - Shadow/SDF passes stubbed (placeholder textures), CMake integration deferred Training infrastructure (Phase 2): - blender_export.py: headless EXR export with all G-buffer render passes - pack_blender_sample.py: EXR → per-channel PNGs (oct-normals, 1/z depth) - pack_photo_sample.py: photo → zero-filled G-buffer sample layout handoff(Gemini): G-buffer phases 3-5 remain (U-Net shaders, CNNv3Effect, parity)