summaryrefslogtreecommitdiff
path: root/cnn_v3/src
diff options
context:
space:
mode:
authorskal <pascal.massimino@gmail.com>2026-03-22 23:17:50 +0100
committerskal <pascal.massimino@gmail.com>2026-03-22 23:17:50 +0100
commit8fd3eda0ed069b1a817261f8f4d6a35c565b3fe4 (patch)
treeba7a61571d6e08d580ce0db9cddb9ad21584da75 /cnn_v3/src
parenta2697faa005337c4d8e8e6376d9e57edadf63f44 (diff)
fix(cnn_v3): shadow pass — 5 bugs fixed, labels in gbuf_viewHEADmain
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.
Diffstat (limited to 'cnn_v3/src')
-rw-r--r--cnn_v3/src/gbuf_view_effect.cc4
-rw-r--r--cnn_v3/src/gbuffer_effect.cc78
2 files changed, 36 insertions, 46 deletions
diff --git a/cnn_v3/src/gbuf_view_effect.cc b/cnn_v3/src/gbuf_view_effect.cc
index 180919d..ccf80b0 100644
--- a/cnn_v3/src/gbuf_view_effect.cc
+++ b/cnn_v3/src/gbuf_view_effect.cc
@@ -10,6 +10,7 @@
#endif
#include "gpu/gpu.h"
+#include "gpu/shader_composer.h"
#include "util/asset_manager.h"
#include "util/fatal_error.h"
@@ -63,7 +64,8 @@ GBufViewEffect::GBufViewEffect(const GpuContext& ctx,
// Shader module
WGPUShaderSourceWGSL wgsl_src = {};
wgsl_src.chain.sType = WGPUSType_ShaderSourceWGSL;
- wgsl_src.code = str_view(gbuf_view_wgsl);
+ const std::string composed = ShaderComposer::Get().Compose({}, gbuf_view_wgsl);
+ wgsl_src.code = str_view(composed.c_str());
WGPUShaderModuleDescriptor shader_desc = {};
shader_desc.nextInChain = &wgsl_src.chain;
WGPUShaderModule shader =
diff --git a/cnn_v3/src/gbuffer_effect.cc b/cnn_v3/src/gbuffer_effect.cc
index c49ab88..b059915 100644
--- a/cnn_v3/src/gbuffer_effect.cc
+++ b/cnn_v3/src/gbuffer_effect.cc
@@ -109,50 +109,29 @@ void GBufferEffect::set_scene() {
};
auto rrange = [&](float lo, float hi) { return lo + rnd() * (hi - lo); };
- // 20 small cubes scattered in a [-2,2]×[-1.5,1.5]×[-1.5,1.5] volume.
- static const int kNumCubes = 20;
- for (int i = 0; i < kNumCubes; ++i) {
+ // 2 large cubes.
+ // 2 large static cubes for shadow debugging.
+ {
Object3D obj(ObjectType::CUBE);
- obj.position = vec3(rrange(-2.0f, 2.0f),
- rrange(-1.5f, 1.5f),
- rrange(-1.5f, 1.5f));
- const float s = rrange(0.10f, 0.25f);
- obj.scale = vec3(s, s, s);
- obj.color = vec4(rrange(0.4f, 1.0f),
- rrange(0.4f, 1.0f),
- rrange(0.4f, 1.0f), 1.0f);
-
- // Random rotation axis (avoid degenerate zero-length axis).
- vec3 axis = vec3(rrange(-1.0f, 1.0f),
- rrange(-1.0f, 1.0f),
- rrange(-1.0f, 1.0f));
- if (axis.len() < 0.01f) axis = vec3(0.0f, 1.0f, 0.0f);
- axis = axis.normalize();
- const float speed = rrange(0.3f, 1.5f) * (rnd() > 0.5f ? 1.0f : -1.0f);
-
+ obj.position = vec3(-1.0f, 0.0f, 0.0f);
+ obj.scale = vec3(0.6f, 0.6f, 0.6f);
+ obj.color = vec4(0.9f, 0.5f, 0.3f, 1.0f);
scene_.add_object(obj);
- cube_anims_.push_back({axis, speed});
+ cube_anims_.push_back({{0.0f, 1.0f, 0.0f}, 0.0f});
}
-
- // 4 pumping spheres at fixed positions; radius modulated by audio_intensity.
- static const vec3 kSpherePos[4] = {
- { 0.0f, 0.0f, 0.0f},
- { 1.5f, 0.5f, -0.5f},
- {-1.5f, -0.5f, 0.5f},
- { 0.0f, 1.0f, 1.0f},
- };
- static const float kBaseSphereRadius[4] = {0.35f, 0.28f, 0.30f, 0.25f};
- for (int i = 0; i < 4; ++i) {
+ {
Object3D obj(ObjectType::SPHERE);
- obj.position = kSpherePos[i];
- const float r = kBaseSphereRadius[i];
- obj.scale = vec3(r, r, r);
- obj.color = vec4(0.85f, 0.60f, 0.95f, 1.0f);
+ obj.position = vec3(1.0f, 0.0f, 0.0f);
+ const float r = 0.9f;
+ obj.scale = vec3(r, r, r);
+ obj.color = vec4(0.3f, 0.6f, 0.9f, 1.0f);
const int idx = (int)scene_.objects.size();
scene_.add_object(obj);
sphere_anims_.push_back({idx, r});
}
+ // (sphere removed for shadow debugging)
+
// Camera: above and in front of the scene, looking at origin.
camera_.set_look_at(vec3(0.0f, 2.5f, 6.0f),
vec3(0.0f, 0.0f, 0.0f),
@@ -213,13 +192,13 @@ void GBufferEffect::render(WGPUCommandEncoder encoder,
// Upload two directional lights.
{
GBufLightsUniforms lu = {};
- lu.params = vec4(2.0f, 0.0f, 0.0f, 0.0f);
+ lu.params = vec4(1.0f, 0.0f, 0.0f, 0.0f);
// Key: warm sun, upper-right-front.
lu.lights[0].direction = vec4(0.408f, 0.816f, 0.408f, 0.0f); // norm(1,2,1)
lu.lights[0].color = vec4(1.00f, 0.92f, 0.78f, 1.0f);
- // Fill: cool sky, upper-left-back.
- lu.lights[1].direction = vec4(-0.577f, 0.577f, -0.577f, 0.0f); // norm(-1,1,-1)
- lu.lights[1].color = vec4(0.40f, 0.45f, 0.80f, 0.4f);
+ // Fill: cool sky, upper-left-back. (disabled for debugging)
+ // lu.lights[1].direction = vec4(-0.577f, 0.577f, -0.577f, 0.0f);
+ // lu.lights[1].color = vec4(0.40f, 0.45f, 0.80f, 0.4f);
lights_uniform_.update(ctx_.queue, lu);
}
@@ -301,7 +280,7 @@ void GBufferEffect::render(WGPUCommandEncoder encoder,
// --- Pass 2: SDF shadow raymarching ---
if (shadow_pipeline_.get() != nullptr) {
- WGPUBindGroupEntry shadow_entries[4] = {};
+ WGPUBindGroupEntry shadow_entries[5] = {};
shadow_entries[0].binding = 0;
shadow_entries[0].buffer = global_uniforms_buf_.buffer;
shadow_entries[0].size = sizeof(GBufGlobalUniforms);
@@ -317,12 +296,15 @@ void GBufferEffect::render(WGPUCommandEncoder encoder,
shadow_entries[3].buffer = lights_uniform_.get().buffer;
shadow_entries[3].size = sizeof(GBufLightsUniforms);
+ shadow_entries[4].binding = 4;
+ shadow_entries[4].textureView = normal_mat_view;
+
WGPUBindGroupLayout shadow_bgl =
wgpuRenderPipelineGetBindGroupLayout(shadow_pipeline_.get(), 0);
WGPUBindGroupDescriptor shadow_bg_desc = {};
shadow_bg_desc.layout = shadow_bgl;
- shadow_bg_desc.entryCount = 4;
+ shadow_bg_desc.entryCount = 5;
shadow_bg_desc.entries = shadow_entries;
WGPUBindGroup shadow_bg =
@@ -448,7 +430,8 @@ void GBufferEffect::upload_scene_data(const Scene& scene,
: (size_t)kGBufMaxObjects);
const mat4 view = camera.get_view_matrix();
- const mat4 proj = camera.get_projection_matrix();
+ mat4 proj = camera.get_projection_matrix();
+ proj.m[5] = -proj.m[5]; // undo post-process Y flip: G-buffer uses integer reads
const mat4 vp = proj * view;
GBufGlobalUniforms gu = {};
@@ -554,7 +537,7 @@ void GBufferEffect::create_raster_pipeline() {
pipe_desc.depthStencil = &ds;
pipe_desc.primitive.topology = WGPUPrimitiveTopology_TriangleList;
pipe_desc.primitive.cullMode = WGPUCullMode_Back;
- pipe_desc.primitive.frontFace = WGPUFrontFace_CW; // Y-flipped perspective
+ pipe_desc.primitive.frontFace = WGPUFrontFace_CCW; // standard (no Y flip)
pipe_desc.multisample.count = 1;
pipe_desc.multisample.mask = 0xFFFFFFFF;
@@ -584,7 +567,7 @@ void GBufferEffect::create_shadow_pipeline() {
WGPUShaderModule shader = wgpuDeviceCreateShaderModule(ctx_.device, &shader_desc);
// BGL: B0=GlobalUniforms, B1=ObjectsBuffer, B2=texture_depth_2d, B3=GBufLightsUniforms
- WGPUBindGroupLayoutEntry bgl_entries[4] = {};
+ WGPUBindGroupLayoutEntry bgl_entries[5] = {};
bgl_entries[0].binding = 0;
bgl_entries[0].visibility =
@@ -607,8 +590,13 @@ void GBufferEffect::create_shadow_pipeline() {
bgl_entries[3].buffer.type = WGPUBufferBindingType_Uniform;
bgl_entries[3].buffer.minBindingSize = sizeof(GBufLightsUniforms);
+ bgl_entries[4].binding = 4;
+ bgl_entries[4].visibility = WGPUShaderStage_Fragment;
+ bgl_entries[4].texture.sampleType = WGPUTextureSampleType_Float;
+ bgl_entries[4].texture.viewDimension = WGPUTextureViewDimension_2D;
+
WGPUBindGroupLayoutDescriptor bgl_desc = {};
- bgl_desc.entryCount = 4;
+ bgl_desc.entryCount = 5;
bgl_desc.entries = bgl_entries;
WGPUBindGroupLayout bgl = wgpuDeviceCreateBindGroupLayout(ctx_.device, &bgl_desc);