summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/effects/shaders.cc3
-rw-r--r--src/effects/shaders.h1
-rw-r--r--src/gpu/demo_effects.h1
-rw-r--r--src/shaders/math/normal.wgsl34
-rw-r--r--src/shaders/ray_sphere.wgsl21
-rw-r--r--src/tests/gpu/test_demo_effects.cc5
6 files changed, 65 insertions, 0 deletions
diff --git a/src/effects/shaders.cc b/src/effects/shaders.cc
index a74d920..8b625ee 100644
--- a/src/effects/shaders.cc
+++ b/src/effects/shaders.cc
@@ -35,6 +35,7 @@ void InitShaderComposer() {
register_if_exists("math/common_utils",
AssetId::ASSET_SHADER_MATH_COMMON_UTILS);
register_if_exists("math/noise", AssetId::ASSET_SHADER_MATH_NOISE);
+ register_if_exists("math/normal", AssetId::ASSET_SHADER_MATH_NORMAL);
register_if_exists("render/shadows", AssetId::ASSET_SHADER_RENDER_SHADOWS);
register_if_exists("render/scene_query_bvh",
AssetId::ASSET_SHADER_RENDER_SCENE_QUERY_BVH);
@@ -50,6 +51,7 @@ void InitShaderComposer() {
register_if_exists("ray_box", AssetId::ASSET_SHADER_RAY_BOX);
register_if_exists("ray_triangle", AssetId::ASSET_SHADER_RAY_TRIANGLE);
+ register_if_exists("ray_sphere", AssetId::ASSET_SHADER_RAY_SPHERE);
register_if_exists("debug/debug_print",
AssetId::ASSET_SHADER_DEBUG_DEBUG_PRINT);
@@ -119,6 +121,7 @@ const char* gbuf_raster_wgsl = SafeGetAsset(AssetId::ASSET_SHADER_GBUF_RASTE
const char* gbuf_pack_wgsl = SafeGetAsset(AssetId::ASSET_SHADER_GBUF_PACK);
const char* gbuf_shadow_wgsl = SafeGetAsset(AssetId::ASSET_SHADER_GBUF_SHADOW);
const char* gbuf_view_wgsl = SafeGetAsset(AssetId::ASSET_SHADER_GBUF_VIEW);
+const char* gbuf_deferred_wgsl = SafeGetAsset(AssetId::ASSET_SHADER_GBUF_DEFERRED);
const char* cnn_v3_enc0_wgsl = SafeGetAsset(AssetId::ASSET_SHADER_CNN_V3_ENC0);
const char* cnn_v3_enc1_wgsl = SafeGetAsset(AssetId::ASSET_SHADER_CNN_V3_ENC1);
const char* cnn_v3_bottleneck_wgsl = SafeGetAsset(AssetId::ASSET_SHADER_CNN_V3_BOTTLENECK);
diff --git a/src/effects/shaders.h b/src/effects/shaders.h
index 1664706..7e1cf02 100644
--- a/src/effects/shaders.h
+++ b/src/effects/shaders.h
@@ -25,6 +25,7 @@ extern const char* gbuf_raster_wgsl;
extern const char* gbuf_pack_wgsl;
extern const char* gbuf_shadow_wgsl;
extern const char* gbuf_view_wgsl;
+extern const char* gbuf_deferred_wgsl;
// CNN v3 inference shaders
extern const char* cnn_v3_enc0_wgsl;
diff --git a/src/gpu/demo_effects.h b/src/gpu/demo_effects.h
index edb4a23..77e5c76 100644
--- a/src/gpu/demo_effects.h
+++ b/src/gpu/demo_effects.h
@@ -36,6 +36,7 @@
#include "../../cnn_v3/src/gbuffer_effect.h"
#include "../../cnn_v3/src/cnn_v3_effect.h"
#include "../../cnn_v3/src/gbuf_view_effect.h"
+#include "../../cnn_v3/src/gbuf_deferred_effect.h"
// TODO: Port CNN effects
// #include "../../cnn_v1/src/cnn_v1_effect.h"
diff --git a/src/shaders/math/normal.wgsl b/src/shaders/math/normal.wgsl
new file mode 100644
index 0000000..5a9a1a9
--- /dev/null
+++ b/src/shaders/math/normal.wgsl
@@ -0,0 +1,34 @@
+// Normal encoding/decoding utilities.
+// Octahedral encoding: losslessly maps unit normals ↔ vec2f in [-1,1]².
+// Storage convention: remap to [0,1] before writing to u8/f16 textures.
+
+// Encode a unit normal to octahedral XY in [-1, 1].
+fn oct_encode(n: vec3f) -> vec2f {
+ let inv_l1 = 1.0 / (abs(n.x) + abs(n.y) + abs(n.z));
+ var p = n.xy * inv_l1;
+ if (n.z < 0.0) {
+ let s = vec2f(select(-1.0, 1.0, p.x >= 0.0),
+ select(-1.0, 1.0, p.y >= 0.0));
+ p = (1.0 - abs(p.yx)) * s;
+ }
+ return p; // [-1, 1]
+}
+
+// Decode octahedral XY in [-1, 1] back to a unit normal.
+fn oct_decode(f: vec2f) -> vec3f {
+ var n = vec3f(f.x, f.y, 1.0 - abs(f.x) - abs(f.y));
+ let t = max(-n.z, 0.0);
+ n.x += select(t, -t, n.x >= 0.0);
+ n.y += select(t, -t, n.y >= 0.0);
+ return normalize(n);
+}
+
+// Convenience: encode + remap to [0, 1] for texture storage.
+fn oct_encode_unorm(n: vec3f) -> vec2f {
+ return oct_encode(n) * 0.5 + vec2f(0.5);
+}
+
+// Convenience: undo [0, 1] remap then decode.
+fn oct_decode_unorm(rg: vec2f) -> vec3f {
+ return oct_decode(rg * 2.0 - vec2f(1.0));
+}
diff --git a/src/shaders/ray_sphere.wgsl b/src/shaders/ray_sphere.wgsl
new file mode 100644
index 0000000..659e144
--- /dev/null
+++ b/src/shaders/ray_sphere.wgsl
@@ -0,0 +1,21 @@
+// Ray-sphere intersection.
+// ro: ray origin, rd: ray direction (must be normalized).
+// center: sphere center, radius: sphere radius.
+// Returns t of the nearest positive intersection, or -1.0 if no hit.
+
+struct RaySphereHit {
+ t: f32, // distance along ray to nearest hit (negative = miss)
+ hit: bool,
+};
+
+fn ray_sphere_intersection(ro: vec3f, rd: vec3f,
+ center: vec3f, radius: f32) -> RaySphereHit {
+ let oc = ro - center;
+ let b = dot(oc, rd);
+ let c = dot(oc, oc) - radius * radius;
+ let disc = b * b - c;
+ if (disc < 0.0) { return RaySphereHit(-1.0, false); }
+ let t = -b - sqrt(disc);
+ if (t < 0.0) { return RaySphereHit(-1.0, false); }
+ return RaySphereHit(t, true);
+}
diff --git a/src/tests/gpu/test_demo_effects.cc b/src/tests/gpu/test_demo_effects.cc
index d6e9c8a..1bb89f9 100644
--- a/src/tests/gpu/test_demo_effects.cc
+++ b/src/tests/gpu/test_demo_effects.cc
@@ -94,6 +94,11 @@ static void test_effects() {
fixture.ctx(),
std::vector<std::string>{"gbuf_feat0", "gbuf_feat1"},
std::vector<std::string>{"gbuf_view_out"}, 0.0f, 1000.0f)},
+ {"GBufDeferredEffect",
+ std::make_shared<GBufDeferredEffect>(
+ fixture.ctx(),
+ std::vector<std::string>{"gbuf_feat0", "gbuf_feat1"},
+ std::vector<std::string>{"gbuf_deferred_out"}, 0.0f, 1000.0f)},
};
int passed = 0;