diff --git a/src/ShaderWorker.ts b/src/ShaderWorker.ts index a935979..2deeb49 100644 --- a/src/ShaderWorker.ts +++ b/src/ShaderWorker.ts @@ -56,6 +56,7 @@ class ShaderWorker { private imageDataCache: LRUCache = new LRUCache(PERFORMANCE.IMAGE_DATA_CACHE_SIZE); private compilationCache: LRUCache = new LRUCache(PERFORMANCE.COMPILATION_CACHE_SIZE); private colorTables: Map = new Map(); + private feedbackBuffer: Float32Array | null = null; constructor() { self.onmessage = (e: MessageEvent) => { @@ -156,6 +157,15 @@ class ShaderWorker { 'y', 't', 'i', + 'r', + 'a', + 'u', + 'v', + 'c', + 'f', + 'd', + 'n', + 'b', 'mouseX', 'mouseY', 'mousePressed', @@ -295,6 +305,11 @@ class ShaderWorker { const data = imageData.data; const startTime = performance.now(); const maxRenderTime = PERFORMANCE.MAX_RENDER_TIME_MS; + + // Initialize feedback buffer if needed + if (!this.feedbackBuffer || this.feedbackBuffer.length !== width * height) { + this.feedbackBuffer = new Float32Array(width * height); + } try { // Use tiled rendering for better timeout handling @@ -392,11 +407,34 @@ class ShaderWorker { const actualY = y + yOffset; try { + // Calculate additional coordinate variables + const u = x / fullWidth; + const v = actualY / fullHeight; + const centerX = fullWidth / 2; + const centerY = fullHeight / 2; + const radius = Math.sqrt((x - centerX) ** 2 + (actualY - centerY) ** 2); + const angle = Math.atan2(actualY - centerY, x - centerX); + const maxDistance = Math.sqrt(centerX ** 2 + centerY ** 2); + const normalizedDistance = radius / maxDistance; + const frameCount = Math.floor(time * 60); + const manhattanDistance = Math.abs(x - centerX) + Math.abs(actualY - centerY); + const noise = (Math.sin(x * 0.1) * Math.cos(actualY * 0.1) + 1) * 0.5; + const feedbackValue = this.feedbackBuffer ? this.feedbackBuffer[pixelIndex] || 0 : 0; + const value = this.compiledFunction!( x, actualY, time, pixelIndex, + radius, + angle, + u, + v, + normalizedDistance, + frameCount, + manhattanDistance, + noise, + feedbackValue, message.mouseX || 0, message.mouseY || 0, message.mousePressed ? 1 : 0, @@ -436,6 +474,11 @@ class ShaderWorker { data[i + 1] = g; data[i + 2] = b; data[i + 3] = 255; + + // Update feedback buffer with current processed value + if (this.feedbackBuffer) { + this.feedbackBuffer[pixelIndex] = safeValue; + } } catch (error) { data[i] = 0; data[i + 1] = 0; diff --git a/src/components/HelpPopup.tsx b/src/components/HelpPopup.tsx index 03c6b7f..d96db3f 100644 --- a/src/components/HelpPopup.tsx +++ b/src/components/HelpPopup.tsx @@ -58,6 +58,30 @@ export function HelpPopup() {

i - Pixel index

+

+ r - Distance from center +

+

+ a - Angle from center (radians) +

+

+ u, v - Normalized coordinates (0.0 to 1.0) +

+

+ c - Normalized center distance (0.0 to 1.0) +

+

+ f - Frame count (discrete timing) +

+

+ d - Manhattan distance from center +

+

+ n - Noise value (0.0 to 1.0) +

+

+ b - Previous frame's value (feedback) +

mouseX, mouseY - Mouse position (0.0 to 1.0)

diff --git a/src/components/ShaderCanvas.tsx b/src/components/ShaderCanvas.tsx index caf6f02..f1b5713 100644 --- a/src/components/ShaderCanvas.tsx +++ b/src/components/ShaderCanvas.tsx @@ -74,13 +74,7 @@ export function ShaderCanvas() { // Handle animation useEffect(() => { if (shaderRef.current) { - const hasTime = shader.code.includes('t'); - if (hasTime) { - shaderRef.current.startAnimation(); - } else { - shaderRef.current.stopAnimation(); - shaderRef.current.render(false); - } + shaderRef.current.startAnimation(); } }, [shader.code]);