diff --git a/src/ShaderWorker.ts b/src/ShaderWorker.ts index a7a9dd1..80c4c9e 100644 --- a/src/ShaderWorker.ts +++ b/src/ShaderWorker.ts @@ -185,7 +185,22 @@ class ShaderWorker { 'midLevel', 'trebleLevel', 'bpm', + '_t', + 'bx', + 'by', + 'sx', + 'sy', + 'qx', + 'qy', ` + // Shader-specific helper functions + const clamp = (value, min, max) => Math.min(Math.max(value, min), max); + const lerp = (a, b, t) => a + (b - a) * t; + const smooth = (edge, x) => { const t = Math.min(Math.max((x - edge) / (1 - edge), 0), 1); return t * t * (3 - 2 * t); }; + const step = (edge, x) => x < edge ? 0 : 1; + const fract = (x) => x - Math.floor(x); + const mix = (a, b, t) => a + (b - a) * t; + // Timeout protection const startTime = performance.now(); let iterations = 0; @@ -223,7 +238,7 @@ class ShaderWorker { private isStaticExpression(code: string): boolean { // Check if code contains any variables using regex for better accuracy - const variablePattern = /\b(x|y|t|i|r|a|u|v|c|f|d|n|b|bn|bs|be|bw|m|l|k|s|e|w|h|p|z|j|o|g|bpm|mouse[XY]|mousePressed|mouseV[XY]|mouseClickTime|touchCount|touch[01][XY]|pinchScale|pinchRotation|accel[XYZ]|gyro[XYZ]|audioLevel|bassLevel|midLevel|trebleLevel)\b/; + const variablePattern = /\b(x|y|t|i|r|a|u|v|c|f|d|n|b|bn|bs|be|bw|m|l|k|s|e|w|h|p|z|j|o|g|bpm|bx|by|sx|sy|qx|qy|mouse[XY]|mousePressed|mouseV[XY]|mouseClickTime|touchCount|touch[01][XY]|pinchScale|pinchRotation|accel[XYZ]|gyro[XYZ]|audioLevel|bassLevel|midLevel|trebleLevel)\b/; return !variablePattern.test(code); } @@ -481,6 +496,14 @@ class ShaderWorker { const jitter = ((x * 73856093 + actualY * 19349663) % 256) / 255; // deterministic per-pixel random const oscillation = Math.sin(time * 2 * Math.PI + radius * 0.1); // wave oscillation const goldenRatio = 1.618033988749; // golden ratio constant + + // Calculate new spatial variables + const bx = x >> 4; // Block x coordinate (16-pixel blocks) + const by = actualY >> 4; // Block y coordinate (16-pixel blocks) + const sx = x - (fullWidth >> 1); // Signed x coordinate (centered at origin) + const sy = actualY - (fullHeight >> 1); // Signed y coordinate (centered at origin) + const qx = x >> 3; // Quarter block x coordinate (8-pixel blocks) + const qy = actualY >> 3; // Quarter block y coordinate (8-pixel blocks) const value = this.compiledFunction!( x, @@ -535,7 +558,14 @@ class ShaderWorker { message.bassLevel || 0, message.midLevel || 0, message.trebleLevel || 0, - message.bpm || 120 + message.bpm || 120, + (mod: number) => time % mod, + bx, + by, + sx, + sy, + qx, + qy ); const safeValue = isFinite(value) ? value : 0; const [r, g, b] = this.calculateColor( @@ -1113,6 +1143,9 @@ class ShaderWorker { processedCode = processedCode.replace(/\bSQRT1_2\b/g, 'Math.SQRT1_2'); processedCode = processedCode.replace(/\bSQRT2\b/g, 'Math.SQRT2'); + // Add custom time function t() with modulo wrapping + processedCode = processedCode.replace(/\bt\s*\(/g, '_t('); + return processedCode; } diff --git a/src/components/HelpPopup.tsx b/src/components/HelpPopup.tsx index 368d44c..7fdf356 100644 --- a/src/components/HelpPopup.tsx +++ b/src/components/HelpPopup.tsx @@ -72,7 +72,7 @@ export function HelpPopup() { x, y - Pixel coordinates

- t - Time (enables animation) + t - Time (enables animation) - also available as t(n) for modulo wrapping

bpm - Current BPM from tap tempo (default: 120) @@ -105,6 +105,15 @@ export function HelpPopup() {

Core Variables - Advanced

+

+ bx, by - Block coordinates (16-pixel chunks, great for pixelated effects) +

+

+ sx, sy - Signed coordinates (centered at origin, negative to positive) +

+

+ qx, qy - Quarter-block coordinates (8-pixel chunks, finer than bx/by) +

n - Noise value (0.0 to 1.0)

@@ -239,20 +248,41 @@ export function HelpPopup() { sin, cos, tan - Trigonometric functions

- abs, sqrt, pow - Absolute, square root, power + asin, acos, atan, atan2 - Inverse trigonometric functions

- floor, ceil, round - Rounding functions + abs, sqrt, cbrt, pow - Absolute, square root, cube root, power

- min, max - Minimum and maximum + floor, ceil, round, trunc - Rounding functions +

+

+ min, max, sign - Minimum, maximum, sign (-1/0/1) +

+

+ log, log10, log2, exp - Logarithmic and exponential +

+

+ clamp(val, min, max) - Constrain value between min and max +

+

+ lerp(a, b, t) - Linear interpolation between a and b +

+

+ smooth(edge, x) - Smooth step function for gradients +

+

+ step(edge, x) - Step function (0 if x<edge, 1 otherwise) +

+

+ fract(x) - Fractional part (x - floor(x)) +

+

+ mix(a, b, t) - Alias for lerp

random - Random number 0-1

-

- log, exp - Natural logarithm, exponential -

PI, E - Math constants