diff options
| author | skal <pascal.massimino@gmail.com> | 2026-02-14 15:13:09 +0100 |
|---|---|---|
| committer | skal <pascal.massimino@gmail.com> | 2026-02-14 15:13:09 +0100 |
| commit | e38be0dbf5816338ff97e2ee2f9adfff2902dc2b (patch) | |
| tree | 42e380626c6f9d0e0137336c8c2dfb68df327dae /workspaces/main | |
| parent | d6cc50eb49275bbc0de21d4c65a5172d5d65f790 (diff) | |
refactor(wgsl): modularize common shader functions
Extracted common WGSL functions into separate files in `common/shaders/` to improve reusability and maintainability.
- Created `common/shaders/render/fullscreen_vs.wgsl` for a reusable fullscreen vertex shader.
- Created `common/shaders/math/color.wgsl` for color conversion and tone mapping functions.
- Created `common/shaders/math/utils.wgsl` for general math utilities.
- Created `common/shaders/render/raymarching.wgsl` for SDF raymarching logic.
- Updated multiple shaders to use these new common snippets via `#include`.
- Fixed the shader asset validation test to correctly handle shaders that include the common vertex shader.
This refactoring makes the shader code more modular and easier to manage.
Diffstat (limited to 'workspaces/main')
| -rw-r--r-- | workspaces/main/assets.txt | 4 | ||||
| -rw-r--r-- | workspaces/main/shaders/chroma_aberration.wgsl | 9 | ||||
| -rw-r--r-- | workspaces/main/shaders/distort.wgsl | 9 | ||||
| -rw-r--r-- | workspaces/main/shaders/scene1.wgsl | 116 | ||||
| -rw-r--r-- | workspaces/main/shaders/solarize.wgsl | 9 | ||||
| -rw-r--r-- | workspaces/main/shaders/vignette.wgsl | 10 |
6 files changed, 16 insertions, 141 deletions
diff --git a/workspaces/main/assets.txt b/workspaces/main/assets.txt index 72a469b..ace1462 100644 --- a/workspaces/main/assets.txt +++ b/workspaces/main/assets.txt @@ -62,6 +62,10 @@ SHADER_RENDER_LIGHTING_UTILS, NONE, ../../common/shaders/render/lighting_utils.w SHADER_MESH, NONE, shaders/mesh_render.wgsl, "Mesh Rasterization Shader" MESH_CUBE, NONE, obj/test_mesh.obj, "A simple cube mesh" DODECAHEDRON, NONE, obj/dodecahedron.obj, "A dodecahedron mesh" +SHADER_RENDER_FULLSCREEN_VS, NONE, ../../common/shaders/render/fullscreen_vs.wgsl, "Fullscreen Vertex Shader" +SHADER_MATH_COLOR, NONE, ../../common/shaders/math/color.wgsl, "Color Functions" +SHADER_MATH_UTILS, NONE, ../../common/shaders/math/utils.wgsl, "Math Utilities" +SHADER_RENDER_RAYMARCHING, NONE, ../../common/shaders/render/raymarching.wgsl, "Raymarching Functions" SHADER_VIGNETTE, NONE, shaders/vignette.wgsl, "Vignette Shader" SHADER_COMPUTE_GEN_NOISE, NONE, ../../common/shaders/compute/gen_noise.wgsl, "GPU Noise Compute Shader" SHADER_COMPUTE_GEN_PERLIN, NONE, ../../common/shaders/compute/gen_perlin.wgsl, "GPU Perlin Noise Compute Shader" diff --git a/workspaces/main/shaders/chroma_aberration.wgsl b/workspaces/main/shaders/chroma_aberration.wgsl index 6c942b7..ee730b1 100644 --- a/workspaces/main/shaders/chroma_aberration.wgsl +++ b/workspaces/main/shaders/chroma_aberration.wgsl @@ -10,14 +10,7 @@ struct ChromaAberrationParams { @group(0) @binding(2) var<uniform> uniforms: CommonUniforms; @group(0) @binding(3) var<uniform> params: ChromaAberrationParams; -@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); -} +#include "render/fullscreen_vs" @fragment fn fs_main(@builtin(position) p: vec4<f32>) -> @location(0) vec4<f32> { let uv = p.xy / uniforms.resolution; diff --git a/workspaces/main/shaders/distort.wgsl b/workspaces/main/shaders/distort.wgsl index 5d35129..607ac60 100644 --- a/workspaces/main/shaders/distort.wgsl +++ b/workspaces/main/shaders/distort.wgsl @@ -11,14 +11,7 @@ struct DistortParams { @group(0) @binding(2) var<uniform> uniforms: CommonUniforms; @group(0) @binding(3) var<uniform> params: DistortParams; -@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); -} +#include "render/fullscreen_vs" @fragment fn fs_main(@builtin(position) p: vec4<f32>) -> @location(0) vec4<f32> { let uv = p.xy / uniforms.resolution; diff --git a/workspaces/main/shaders/scene1.wgsl b/workspaces/main/shaders/scene1.wgsl index 7af3811..2a811f7 100644 --- a/workspaces/main/shaders/scene1.wgsl +++ b/workspaces/main/shaders/scene1.wgsl @@ -2,29 +2,15 @@ // Source: Saturday cubism experiment by skal #include "common_uniforms" +#include "math/color" +#include "math/utils" +#include "sdf_primitives" +#include "render/raymarching" @group(0) @binding(0) var<uniform> uniforms: CommonUniforms; const PI: f32 = 3.141592654; const TAU: f32 = 6.283185307; -const TOLERANCE: f32 = 0.0005; -const MAX_RAY_LENGTH: f32 = 20.0; -const MAX_RAY_MARCHES: i32 = 80; -const MAX_SHD_MARCHES: i32 = 20; -const NORM_OFF: f32 = 0.005; - -fn rot(a: f32) -> mat2x2<f32> { - let c = cos(a); - let s = sin(a); - return mat2x2<f32>(c, s, -s, c); -} - -// 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); -} // Colors (precomputed HSV conversions) const skyCol = vec3<f32>(0.176, 0.235, 0.25); // HSV(0.57, 0.90, 0.25) @@ -38,44 +24,10 @@ const sunDir1 = vec3<f32>(0.0, 0.04997, -0.99875); // normalize(0, 0.05, -1) const lightPos1 = vec3<f32>(10.0, 10.0, 10.0); const lightPos2 = vec3<f32>(-10.0, 10.0, -10.0); -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))); -} - -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)); -} - -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); -} - fn rayPlane(ro: vec3<f32>, rd: vec3<f32>, plane: vec4<f32>) -> f32 { return -(dot(ro, plane.xyz) + plane.w) / dot(rd, plane.xyz); } -fn box2d(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); -} - -fn box3d(p: vec3<f32>, b: vec3<f32>) -> f32 { - let q = abs(p) - b; - return length(max(q, vec3<f32>(0.0))) + min(max(q.x, max(q.y, q.z)), 0.0); -} - -fn sphere(p: vec3<f32>, r: f32) -> f32 { - return length(p) - r; -} - var<private> g_rot0: mat2x2<f32>; fn render0(ro: vec3<f32>, rd: vec3<f32>) -> vec3<f32> { @@ -90,7 +42,7 @@ fn render0(ro: vec3<f32>, rd: vec3<f32>) -> vec3<f32> { if (tp1 > 0.0) { let pos = ro + tp1 * rd; let pp = pos.xz; - let db = box2d(pp, vec2<f32>(5.0, 9.0)) - 3.0; + let db = sdBox2D(pp, vec2<f32>(5.0, 9.0)) - 3.0; col += vec3<f32>(4.0) * skyCol * rd.y * rd.y * smoothstep(0.25, 0.0, db); col += vec3<f32>(0.8) * skyCol * exp(-0.5 * max(db, 0.0)); } @@ -106,12 +58,12 @@ fn df(p_in: vec3<f32>) -> f32 { // Cube var pc = p; pc -= vec3<f32>(-1.9, 0.0, 0.0); - let dCube = box3d(pc, vec3<f32>(1.6)); + let dCube = sdBox(pc, vec3<f32>(1.6)); // Sphere var ps = p; ps -= vec3<f32>(1.3, 0.0, 0.0); - let dSphere = sphere(ps, 1.2); + let dSphere = sdSphere(ps, 1.2); // Ground plane let dPlane = p.y + 1.0; @@ -123,51 +75,6 @@ fn df(p_in: vec3<f32>) -> f32 { return d; } -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); -} - -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; -} - -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; - 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; -} - fn boxCol(col: vec3<f32>, nsp: vec3<f32>, rd: vec3<f32>, nnor: vec3<f32>, nrcol: vec3<f32>, nshd1: f32, nshd2: f32) -> vec3<f32> { var nfre = 1.0 + dot(rd, nnor); nfre *= nfre; @@ -236,14 +143,7 @@ fn effect(p: vec2<f32>) -> vec3<f32> { return render1(ro, rd); } -@vertex fn vs_main(@builtin(vertex_index) i: u32) -> @builtin(position) vec4<f32> { - var pos = array<vec2<f32>, 3>( - vec2<f32>(-1.0, -1.0), - vec2<f32>(3.0, -1.0), - vec2<f32>(-1.0, 3.0) - ); - return vec4<f32>(pos[i], 0.0, 1.0); -} +#include "render/fullscreen_vs" @fragment fn fs_main(@builtin(position) p: vec4<f32>) -> @location(0) vec4<f32> { // Flip Y to match ShaderToy convention (origin at bottom-left) diff --git a/workspaces/main/shaders/solarize.wgsl b/workspaces/main/shaders/solarize.wgsl index de15dfc..0a69b83 100644 --- a/workspaces/main/shaders/solarize.wgsl +++ b/workspaces/main/shaders/solarize.wgsl @@ -5,14 +5,7 @@ @group(0) @binding(2) var<uniform> uniforms: CommonUniforms; -@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); -} +#include "render/fullscreen_vs" @fragment fn fs_main(@builtin(position) p: vec4<f32>) -> @location(0) vec4<f32> { let uv = p.xy / uniforms.resolution; diff --git a/workspaces/main/shaders/vignette.wgsl b/workspaces/main/shaders/vignette.wgsl index b129883..c4d0389 100644 --- a/workspaces/main/shaders/vignette.wgsl +++ b/workspaces/main/shaders/vignette.wgsl @@ -10,15 +10,7 @@ struct VignetteParams { @group(0) @binding(2) var<uniform> common_uniforms: CommonUniforms; @group(0) @binding(3) var<uniform> params: VignetteParams; -@vertex -fn vs_main(@builtin(vertex_index) vertex_idx: u32) -> @builtin(position) vec4<f32> { - var pos = array<vec2<f32>, 3>( - vec2<f32>(-1.0, -1.0), - vec2<f32>(3.0, -1.0), - vec2<f32>(-1.0, 3.0) - ); - return vec4<f32>(pos[vertex_idx], 0.0, 1.0); -} +#include "render/fullscreen_vs" @fragment fn fs_main(@builtin(position) pos: vec4<f32>) -> @location(0) vec4<f32> { |
