summaryrefslogtreecommitdiff
path: root/cnn_v3/shaders/gbuf_shadow.wgsl
diff options
context:
space:
mode:
authorskal <pascal.massimino@gmail.com>2026-03-22 23:51:40 +0100
committerskal <pascal.massimino@gmail.com>2026-03-22 23:51:40 +0100
commit12d5d5f1762a0c00405950b6ff5e564880f0ff36 (patch)
treeb6e03dbecd424f8a4c02c815b4fec9a160529d8e /cnn_v3/shaders/gbuf_shadow.wgsl
parent8fd3eda0ed069b1a817261f8f4d6a35c565b3fe4 (diff)
refactor(cnn_v3): simplify sphere SDF in shadow pass, remove per-frame alloc
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.
Diffstat (limited to 'cnn_v3/shaders/gbuf_shadow.wgsl')
-rw-r--r--cnn_v3/shaders/gbuf_shadow.wgsl34
1 files changed, 26 insertions, 8 deletions
diff --git a/cnn_v3/shaders/gbuf_shadow.wgsl b/cnn_v3/shaders/gbuf_shadow.wgsl
index 735e47c..6c81d66 100644
--- a/cnn_v3/shaders/gbuf_shadow.wgsl
+++ b/cnn_v3/shaders/gbuf_shadow.wgsl
@@ -28,7 +28,9 @@ struct GBufLightsUniforms {
// Stub required by render/raymarching (shadow() / rayMarch() call df()).
fn df(p: vec3f) -> f32 { return MAX_RAY_LENGTH; }
-// SDF of the full scene: proxy box for each object transformed to local space.
+// SDF of the full scene.
+// Sphere: direct world-space formula (exact, no matrix multiply).
+// Box/Torus/Plane: local-space transform + uniform-scale correction.
fn dfWithID(p: vec3f) -> RayMarchResult {
var res: RayMarchResult;
res.distance = MAX_RAY_LENGTH;
@@ -38,16 +40,32 @@ fn dfWithID(p: vec3f) -> RayMarchResult {
let n = u32(globals.params.x);
for (var i = 0u; i < n; i++) {
let obj = object_data.objects[i];
- let lp = (obj.inv_model * vec4f(p, 1.0)).xyz;
let obj_type = u32(obj.params.x);
- // Scale factor: convert local-space SDF to world-space distance.
- let scale = length(obj.model[0].xyz);
var d: f32;
switch obj_type {
- case 1u: { d = sdSphere(lp, 1.0) * scale; } // SPHERE
- case 2u: { d = sdPlane(lp, vec3f(0.0, 1.0, 0.0), obj.params.y); } // PLANE
- case 3u: { d = sdTorus(lp, vec2f(0.8, 0.2)) * scale; } // TORUS
- default: { d = sdBox(lp, vec3f(1.0)) * scale; } // CUBE (0) + fallback
+ case 1u: {
+ // SPHERE: direct world-space SDF — avoids matrix multiply, exact.
+ let c = obj.model[3].xyz;
+ let r = length(obj.model[0].xyz);
+ d = length(p - c) - r;
+ }
+ case 2u: {
+ // PLANE
+ let lp = (obj.inv_model * vec4f(p, 1.0)).xyz;
+ d = sdPlane(lp, vec3f(0.0, 1.0, 0.0), obj.params.y);
+ }
+ case 3u: {
+ // TORUS
+ let lp = (obj.inv_model * vec4f(p, 1.0)).xyz;
+ let scale = length(obj.model[0].xyz);
+ d = sdTorus(lp, vec2f(0.8, 0.2)) * scale;
+ }
+ default: {
+ // CUBE (0) + fallback — uniform scale assumed.
+ let lp = (obj.inv_model * vec4f(p, 1.0)).xyz;
+ let scale = length(obj.model[0].xyz);
+ d = sdBox(lp, vec3f(1.0)) * scale;
+ }
}
if (d < res.distance) {
res.distance = d;