summaryrefslogtreecommitdiff
path: root/common/shaders
diff options
context:
space:
mode:
Diffstat (limited to 'common/shaders')
-rw-r--r--common/shaders/math/color.wgsl27
-rw-r--r--common/shaders/math/utils.wgsl14
-rw-r--r--common/shaders/render/fullscreen_vs.wgsl10
-rw-r--r--common/shaders/render/raymarching.wgsl59
-rw-r--r--common/shaders/sdf_primitives.wgsl5
5 files changed, 115 insertions, 0 deletions
diff --git a/common/shaders/math/color.wgsl b/common/shaders/math/color.wgsl
new file mode 100644
index 0000000..b63c915
--- /dev/null
+++ b/common/shaders/math/color.wgsl
@@ -0,0 +1,27 @@
+// Common color space and tone mapping functions.
+
+// sRGB to Linear approximation
+// Note: Assumes input is in sRGB color space.
+fn sRGB(t: vec3<f32>) -> vec3<f32> {
+ return mix(1.055 * pow(t, vec3<f32>(1.0/2.4)) - 0.055, 12.92 * t, step(t, vec3<f32>(0.0031308)));
+}
+
+// ACES Filmic Tone Mapping (Approximate)
+// A common tone mapping algorithm used in games and film.
+fn aces_approx(v_in: vec3<f32>) -> vec3<f32> {
+ var v = max(v_in, vec3<f32>(0.0));
+ v *= 0.6;
+ let a = 2.51;
+ let b = 0.03;
+ let c = 2.43;
+ let d = 0.59;
+ let e = 0.14;
+ return clamp((v * (a * v + b)) / (v * (c * v + d) + e), vec3<f32>(0.0), vec3<f32>(1.0));
+}
+
+// HSV to RGB conversion
+const hsv2rgb_K = vec4<f32>(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
+fn hsv2rgb(c: vec3<f32>) -> vec3<f32> {
+ let p = abs(fract(c.xxx + hsv2rgb_K.xyz) * 6.0 - hsv2rgb_K.www);
+ return c.z * mix(hsv2rgb_K.xxx, clamp(p - hsv2rgb_K.xxx, vec3<f32>(0.0), vec3<f32>(1.0)), c.y);
+}
diff --git a/common/shaders/math/utils.wgsl b/common/shaders/math/utils.wgsl
new file mode 100644
index 0000000..85f0bdf
--- /dev/null
+++ b/common/shaders/math/utils.wgsl
@@ -0,0 +1,14 @@
+// General-purpose math utility functions.
+
+// Returns a 2x2 rotation matrix.
+fn rot(a: f32) -> mat2x2<f32> {
+ let c = cos(a);
+ let s = sin(a);
+ return mat2x2<f32>(c, s, -s, c);
+}
+
+// Fast approximation of tanh.
+fn tanh_approx(x: f32) -> f32 {
+ let x2 = x * x;
+ return clamp(x * (27.0 + x2) / (27.0 + 9.0 * x2), -1.0, 1.0);
+}
diff --git a/common/shaders/render/fullscreen_vs.wgsl b/common/shaders/render/fullscreen_vs.wgsl
new file mode 100644
index 0000000..a68604b
--- /dev/null
+++ b/common/shaders/render/fullscreen_vs.wgsl
@@ -0,0 +1,10 @@
+// Common vertex shader for fullscreen post-processing effects.
+// Draws a single triangle that covers the entire screen.
+@vertex fn vs_main(@builtin(vertex_index) i: u32) -> @builtin(position) vec4<f32> {
+ var pos = array<vec2<f32>, 3>(
+ vec2<f32>(-1, -1),
+ vec2<f32>(3, -1),
+ vec2<f32>(-1, 3)
+ );
+ return vec4<f32>(pos[i], 0.0, 1.0);
+}
diff --git a/common/shaders/render/raymarching.wgsl b/common/shaders/render/raymarching.wgsl
new file mode 100644
index 0000000..5a86840
--- /dev/null
+++ b/common/shaders/render/raymarching.wgsl
@@ -0,0 +1,59 @@
+// Common functions for Signed Distance Field (SDF) raymarching.
+// These functions require the user to define a `df(vec3<f32>) -> f32` function
+// which represents the scene's distance field.
+
+const TOLERANCE: f32 = 0.0005;
+const MAX_RAY_LENGTH: f32 = 20.0;
+const MAX_RAY_MARCHES: i32 = 80;
+const NORM_OFF: f32 = 0.005;
+
+// Computes the surface normal of the distance field at a point `pos`.
+fn normal(pos: vec3<f32>) -> vec3<f32> {
+ let eps = vec2<f32>(NORM_OFF, 0.0);
+ var nor: vec3<f32>;
+ nor.x = df(pos + eps.xyy) - df(pos - eps.xyy);
+ nor.y = df(pos + eps.yxy) - df(pos - eps.yxy);
+ nor.z = df(pos + eps.yyx) - df(pos - eps.yyx);
+ return normalize(nor);
+}
+
+// Performs the raymarching operation.
+// Returns the distance along the ray to the surface, or MAX_RAY_LENGTH if no surface is hit.
+fn rayMarch(ro: vec3<f32>, rd: vec3<f32>, initt: f32) -> f32 {
+ var t = initt;
+ for (var i = 0; i < MAX_RAY_MARCHES; i++) {
+ if (t > MAX_RAY_LENGTH) {
+ t = MAX_RAY_LENGTH;
+ break;
+ }
+ let d = df(ro + rd * t);
+ if (d < TOLERANCE) {
+ break;
+ }
+ t += d;
+ }
+ return t;
+}
+
+// Computes a soft shadow for a given point.
+fn shadow(lp: vec3<f32>, ld: vec3<f32>, mint: f32, maxt: f32) -> f32 {
+ let ds = 1.0 - 0.4;
+ var t = mint;
+ var nd = 1e6;
+ let soff = 0.05;
+ let smul = 1.5;
+ let MAX_SHD_MARCHES = 20;
+
+ for (var i = 0; i < MAX_SHD_MARCHES; i++) {
+ let p = lp + ld * t;
+ let d = df(p);
+ if (d < TOLERANCE || t >= maxt) {
+ let sd = 1.0 - exp(-smul * max(t / maxt - soff, 0.0));
+ return select(mix(sd, 1.0, smoothstep(0.0, 0.025, nd)), sd, t >= maxt);
+ }
+ nd = min(nd, d);
+ t += ds * d;
+ }
+ let sd = 1.0 - exp(-smul * max(t / maxt - soff, 0.0));
+ return sd;
+}
diff --git a/common/shaders/sdf_primitives.wgsl b/common/shaders/sdf_primitives.wgsl
index 31bbe2d..407fb29 100644
--- a/common/shaders/sdf_primitives.wgsl
+++ b/common/shaders/sdf_primitives.wgsl
@@ -12,3 +12,8 @@ fn sdTorus(p: vec3<f32>, t: vec2<f32>) -> f32 {
fn sdPlane(p: vec3<f32>, n: vec3<f32>, h: f32) -> f32 {
return dot(p, n) + h;
}
+
+fn sdBox2D(p: vec2<f32>, b: vec2<f32>) -> f32 {
+ let d = abs(p) - b;
+ return length(max(d, vec2<f32>(0.0))) + min(max(d.x, d.y), 0.0);
+}