Migrate Vite SPA to Hugo (hugo-coder, dark) with WebGPU background

- Hugo static site at root: config, content (home/about/resume/blog + 5 projects),
  data/resume.yaml, custom layouts (gpu background, resume renderer, projects list),
  dark theme with canvas behind content
- gpu-bg/: extracted WebGPU/WebGL2 spiral engine as a Vite sub-package; slim bootstrap
  drops router/overlay/text renderer; fixed uniforms (scene0/dim0); self-contained engine.js
- archive/: retired Vite SPA preserved (router, overlay, data, engine/text orphaned)
- 3-stage Dockerfile (node -> hugo extended/dart-sass -> nginx), static nginx config
- DEPLOYMENT.md handover + README rewrite; pre-hugo rollback tag
This commit is contained in:
2026-08-21 03:39:42 +02:00
parent 3ad5cf55e3
commit 9ea85db5ce
74 changed files with 3170 additions and 75 deletions

View File

@@ -0,0 +1,108 @@
struct Uniforms {
resolution: vec2<f32>,
time: f32,
scene: f32,
mouse: vec2<f32>,
date: vec4<f32>,
sampleRate: vec4<f32>,
stemMultipliers: array<vec4<f32>, 8>,
};
@group(0) @binding(0) var<uniform> u: Uniforms;
struct VsOut {
@builtin(position) pos: vec4<f32>,
@location(0) uv: vec2<f32>,
};
@vertex
fn vs(@builtin(vertex_index) i: u32) -> VsOut {
let p = array<vec2<f32>, 3>(
vec2<f32>(-1.0, -3.0),
vec2<f32>(-1.0, 1.0),
vec2<f32>(3.0, 1.0),
);
let clip = p[i];
var out: VsOut;
out.pos = vec4<f32>(clip, 0.0, 1.0);
out.uv = clip;
return out;
}
@fragment
fn fs(in: VsOut) -> @location(0) vec4<f32> {
let res = u.resolution;
let fragCoord = (in.uv * vec2<f32>(0.5) + vec2<f32>(0.5)) * res;
var uv = (fragCoord - 0.5 * res) / res.y;
let slowTime = u.time * 0.2;
let bgGrey = vec3<f32>(0.11, 0.11, 0.12);
let cardGrey = vec3<f32>(0.30, 0.32, 0.36);
let coreWhite = vec3<f32>(0.90, 0.95, 0.90);
// ---------- palette keyed by scene ----------
let scene0 = vec3<f32>(0.20, 0.75, 0.20); // HERO – emerald
let scene1 = vec3<f32>(0.85, 0.55, 0.20); // ABOUT – amber
let scene2 = vec3<f32>(0.25, 0.60, 0.95); // PROJECTS – cobalt
let scene3 = vec3<f32>(0.90, 0.35, 0.55); // CONTACT – rose
let sFloor = i32(clamp(floor(u.scene), 0.0, 3.0));
let sCeil = i32(clamp(ceil(u.scene), 0.0, 3.0));
var c0 = scene0;
c0 = select(c0, scene1, sFloor == 1);
c0 = select(c0, scene2, sFloor == 2);
c0 = select(c0, scene3, sFloor == 3);
var c1 = scene0;
c1 = select(c1, scene1, sCeil == 1);
c1 = select(c1, scene2, sCeil == 2);
c1 = select(c1, scene3, sCeil == 3);
let tBlend = u.scene - floor(u.scene);
let sceneAccent = mix(c0, c1, tBlend * tBlend * (3.0 - 2.0 * tBlend));
// ---------- mouse-reactive distortion ----------
let mousePos = (u.mouse - 0.5 * res) / res.y;
let distMouse = length(uv - mousePos);
let influence = exp(-distMouse * 7.0);
uv += (mousePos - uv) * influence * 0.12;
let angle = atan2(uv.y, uv.x);
let radius = length(uv);
let baseSpiral = angle + (radius * 8.0) - slowTime;
let ripple = sin(radius * 15.0 - (u.time * 0.5)) * 0.08;
let distortedSpiral = baseSpiral + ripple;
let armCount = 2.0;
let rChannel = smoothstep(0.05, 0.55, abs(sin((distortedSpiral + 0.04) * armCount)));
let gChannel = smoothstep(0.05, 0.55, abs(sin(distortedSpiral * armCount)));
let bChannel = smoothstep(0.05, 0.55, abs(sin((distortedSpiral - 0.04) * armCount)));
let patternChannels = vec3<f32>(rChannel, gChannel, bChannel);
let coreNeon = vec3<f32>(0.02 / (patternChannels + 0.025));
let spiralColor = mix(cardGrey, sceneAccent, patternChannels.g);
let primarySpiral = coreNeon * spiralColor;
let ringWave = sin(radius * 12.0 - (u.time * 1.5));
let sharpRing = smoothstep(0.85, 0.95, ringWave);
let ringMask = sharpRing * smoothstep(0.7, 0.1, radius);
let secondaryRings = cardGrey * ringMask * 0.4;
let vignette = smoothstep(0.95, 0.4, radius);
var finalColor = bgGrey + secondaryRings;
finalColor = mix(finalColor, primarySpiral, 0.85);
let centerLight = 0.015 / (radius + 0.02);
finalColor += centerLight * coreWhite;
// soft cursor glow
finalColor += exp(-distMouse * 4.0) * 0.03 * sceneAccent;
// ---------- dim when not on the home page (u.date.x controls it) ----------
let dim = u.date.x;
finalColor = mix(finalColor, vec3<f32>(0.0), dim);
return vec4<f32>(finalColor * vignette, 1.0);
}