summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cnn_v3/shaders/gbuf_raster.wgsl12
-rw-r--r--src/effects/shaders.cc1
-rw-r--r--src/shaders/ray_sphere.wgsl21
-rw-r--r--workspaces/main/assets.txt1
4 files changed, 27 insertions, 8 deletions
diff --git a/cnn_v3/shaders/gbuf_raster.wgsl b/cnn_v3/shaders/gbuf_raster.wgsl
index fa2dfd5..aed0e72 100644
--- a/cnn_v3/shaders/gbuf_raster.wgsl
+++ b/cnn_v3/shaders/gbuf_raster.wgsl
@@ -5,6 +5,7 @@
#include "common_uniforms"
#include "math/normal"
+#include "ray_sphere"
@group(0) @binding(0) var<uniform> globals: GlobalUniforms;
@group(0) @binding(1) var<storage, read> object_data: ObjectsBuffer;
@@ -93,14 +94,9 @@ fn fs_main(in: VertexOutput) -> GBufOutput {
let sphere_radius = length(obj.model[0].xyz); // uniform scale in col0
let cam_pos = globals.camera_pos_time.xyz;
let rd = normalize(in.world_pos - cam_pos);
- let oc = cam_pos - sphere_center;
- let b = dot(oc, rd);
- let c = dot(oc, oc) - sphere_radius * sphere_radius;
- let disc = b * b - c;
- if (disc < 0.0) { discard; }
- let t = -b - sqrt(disc);
- if (t < 0.0) { discard; }
- let hit = cam_pos + rd * t;
+ let isect = ray_sphere_intersection(cam_pos, rd, sphere_center, sphere_radius);
+ if (!isect.hit) { discard; }
+ let hit = cam_pos + rd * isect.t;
world_normal = normalize(hit - sphere_center);
// Reproject hit point to get correct clip-space depth.
let clip_hit = globals.view_proj * vec4f(hit, 1.0);
diff --git a/src/effects/shaders.cc b/src/effects/shaders.cc
index a6c1b64..8b625ee 100644
--- a/src/effects/shaders.cc
+++ b/src/effects/shaders.cc
@@ -51,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);
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/workspaces/main/assets.txt b/workspaces/main/assets.txt
index d436319..b96b4c4 100644
--- a/workspaces/main/assets.txt
+++ b/workspaces/main/assets.txt
@@ -38,6 +38,7 @@ SHADER_SDF_SHAPES, WGSL, ../../src/shaders/math/sdf_shapes.wgsl, "SDF Shapes (2D
SHADER_LIGHTING, WGSL, ../../src/shaders/lighting.wgsl, "Lighting Snippet"
SHADER_RAY_BOX, WGSL, ../../src/shaders/ray_box.wgsl, "Ray-Box Intersection Snippet"
SHADER_RAY_TRIANGLE, WGSL, ../../src/shaders/ray_triangle.wgsl, "Ray-Triangle Intersection Snippet (Möller-Trumbore)"
+SHADER_RAY_SPHERE, WGSL, ../../src/shaders/ray_sphere.wgsl, "Ray-Sphere Intersection Snippet"
SHADER_MAIN, WGSL, shaders/main_shader.wgsl, "Main Heptagon Shader"
SHADER_PARTICLE_COMPUTE, WGSL, ../../src/effects/particle_compute.wgsl, "Particle Compute Shader"
SHADER_PARTICLE_RENDER, WGSL, ../../src/effects/particle_render.wgsl, "Particle Render Shader"