diff options
| author | Dhravya Shah <[email protected]> | 2025-09-18 20:34:18 -0700 |
|---|---|---|
| committer | Dhravya Shah <[email protected]> | 2025-09-18 21:03:49 -0700 |
| commit | 1fcb56908920da386900abb4ce2383374a625c72 (patch) | |
| tree | 0f9d7f695d4c9b1b85be3950fc869e0061dff3ed /packages/lib/glass-effect-manager.ts | |
| parent | refetching logic change (diff) | |
| download | supermemory-09-18-formatting.tar.xz supermemory-09-18-formatting.zip | |
formatting09-18-formatting
Diffstat (limited to 'packages/lib/glass-effect-manager.ts')
| -rw-r--r-- | packages/lib/glass-effect-manager.ts | 196 |
1 files changed, 98 insertions, 98 deletions
diff --git a/packages/lib/glass-effect-manager.ts b/packages/lib/glass-effect-manager.ts index 291a30aa..03a79734 100644 --- a/packages/lib/glass-effect-manager.ts +++ b/packages/lib/glass-effect-manager.ts @@ -1,56 +1,56 @@ // Singleton WebGL context manager for glass effects class GlassEffectManager { - private static instance: GlassEffectManager | null = null - private canvas: HTMLCanvasElement | null = null - private gl: WebGLRenderingContext | null = null - private program: WebGLProgram | null = null - private uniforms: Record<string, WebGLUniformLocation | null> = {} - private effects: Map<string, EffectInstance> = new Map() - private animationFrame: number | null = null - private startTime: number = performance.now() - private mousePositions: Map<string, { x: number; y: number }> = new Map() + private static instance: GlassEffectManager | null = null; + private canvas: HTMLCanvasElement | null = null; + private gl: WebGLRenderingContext | null = null; + private program: WebGLProgram | null = null; + private uniforms: Record<string, WebGLUniformLocation | null> = {}; + private effects: Map<string, EffectInstance> = new Map(); + private animationFrame: number | null = null; + private startTime: number = performance.now(); + private mousePositions: Map<string, { x: number; y: number }> = new Map(); static getInstance(): GlassEffectManager { if (!GlassEffectManager.instance) { - GlassEffectManager.instance = new GlassEffectManager() + GlassEffectManager.instance = new GlassEffectManager(); } - return GlassEffectManager.instance + return GlassEffectManager.instance; } private constructor() { - this.initializeContext() + this.initializeContext(); } private initializeContext() { // Create offscreen canvas - this.canvas = document.createElement("canvas") - this.canvas.width = 1024 // Default size, will be adjusted - this.canvas.height = 1024 + this.canvas = document.createElement("canvas"); + this.canvas.width = 1024; // Default size, will be adjusted + this.canvas.height = 1024; this.gl = this.canvas.getContext("webgl", { alpha: true, premultipliedAlpha: false, preserveDrawingBuffer: true, - }) + }); if (!this.gl) { - console.error("WebGL not supported") - return + console.error("WebGL not supported"); + return; } - this.setupShaders() - this.startRenderLoop() + this.setupShaders(); + this.startRenderLoop(); } private setupShaders() { - if (!this.gl) return + if (!this.gl) return; const vsSource = ` attribute vec2 position; void main() { gl_Position = vec4(position, 0.0, 1.0); } - ` + `; const fsSource = ` precision mediump float; @@ -106,48 +106,48 @@ class GlassEffectManager { gl_FragColor = vec4(glassColor, alpha); } - ` + `; const createShader = (type: number, source: string) => { - const shader = this.gl!.createShader(type) - if (!shader) return null + const shader = this.gl!.createShader(type); + if (!shader) return null; - this.gl!.shaderSource(shader, source) - this.gl!.compileShader(shader) + this.gl!.shaderSource(shader, source); + this.gl!.compileShader(shader); if (!this.gl!.getShaderParameter(shader, this.gl!.COMPILE_STATUS)) { - console.error("Shader error:", this.gl!.getShaderInfoLog(shader)) - this.gl!.deleteShader(shader) - return null + console.error("Shader error:", this.gl!.getShaderInfoLog(shader)); + this.gl!.deleteShader(shader); + return null; } - return shader - } + return shader; + }; - const vs = createShader(this.gl.VERTEX_SHADER, vsSource) - const fs = createShader(this.gl.FRAGMENT_SHADER, fsSource) - if (!vs || !fs) return + const vs = createShader(this.gl.VERTEX_SHADER, vsSource); + const fs = createShader(this.gl.FRAGMENT_SHADER, fsSource); + if (!vs || !fs) return; - this.program = this.gl.createProgram() - if (!this.program) return + this.program = this.gl.createProgram(); + if (!this.program) return; - this.gl.attachShader(this.program, vs) - this.gl.attachShader(this.program, fs) - this.gl.linkProgram(this.program) + this.gl.attachShader(this.program, vs); + this.gl.attachShader(this.program, fs); + this.gl.linkProgram(this.program); // biome-ignore lint/correctness/useHookAtTopLevel: Well, not a hook - this.gl.useProgram(this.program) + this.gl.useProgram(this.program); // Buffer setup - const buffer = this.gl.createBuffer() - this.gl.bindBuffer(this.gl.ARRAY_BUFFER, buffer) + const buffer = this.gl.createBuffer(); + this.gl.bindBuffer(this.gl.ARRAY_BUFFER, buffer); this.gl.bufferData( this.gl.ARRAY_BUFFER, new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]), this.gl.STATIC_DRAW, - ) + ); - const position = this.gl.getAttribLocation(this.program, "position") - this.gl.enableVertexAttribArray(position) - this.gl.vertexAttribPointer(position, 2, this.gl.FLOAT, false, 0, 0) + const position = this.gl.getAttribLocation(this.program, "position"); + this.gl.enableVertexAttribArray(position); + this.gl.vertexAttribPointer(position, 2, this.gl.FLOAT, false, 0, 0); // Store uniform locations this.uniforms = { @@ -155,11 +155,11 @@ class GlassEffectManager { time: this.gl.getUniformLocation(this.program, "iTime"), mouse: this.gl.getUniformLocation(this.program, "iMouse"), expanded: this.gl.getUniformLocation(this.program, "iExpanded"), - } + }; // Enable blending - this.gl.enable(this.gl.BLEND) - this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA) + this.gl.enable(this.gl.BLEND); + this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA); } registerEffect( @@ -168,8 +168,8 @@ class GlassEffectManager { isExpanded: boolean, ): () => void { // Ensure minimum dimensions - const width = Math.max(1, targetCanvas.width) - const height = Math.max(1, targetCanvas.height) + const width = Math.max(1, targetCanvas.width); + const height = Math.max(1, targetCanvas.height); const effect: EffectInstance = { id, @@ -177,58 +177,58 @@ class GlassEffectManager { isExpanded, width, height, - } + }; - this.effects.set(id, effect) - this.mousePositions.set(id, { x: 0, y: 0 }) + this.effects.set(id, effect); + this.mousePositions.set(id, { x: 0, y: 0 }); // Return cleanup function return () => { - this.effects.delete(id) - this.mousePositions.delete(id) + this.effects.delete(id); + this.mousePositions.delete(id); if (this.effects.size === 0 && this.animationFrame) { - cancelAnimationFrame(this.animationFrame) - this.animationFrame = null + cancelAnimationFrame(this.animationFrame); + this.animationFrame = null; } - } + }; } updateMousePosition(id: string, x: number, y: number) { - this.mousePositions.set(id, { x, y }) + this.mousePositions.set(id, { x, y }); } updateExpanded(id: string, isExpanded: boolean) { - const effect = this.effects.get(id) + const effect = this.effects.get(id); if (effect) { - effect.isExpanded = isExpanded + effect.isExpanded = isExpanded; } } updateSize(id: string, width: number, height: number) { - const effect = this.effects.get(id) + const effect = this.effects.get(id); if (effect) { // Ensure minimum dimensions - effect.width = Math.max(1, width) - effect.height = Math.max(1, height) + effect.width = Math.max(1, width); + effect.height = Math.max(1, height); } } private startRenderLoop() { const render = () => { if (!this.gl || !this.program || this.effects.size === 0) { - this.animationFrame = requestAnimationFrame(render) - return + this.animationFrame = requestAnimationFrame(render); + return; } - const currentTime = (performance.now() - this.startTime) / 1000 + const currentTime = (performance.now() - this.startTime) / 1000; // Render each effect for (const [id, effect] of Array.from(this.effects)) { - const mousePos = this.mousePositions.get(id) || { x: 0, y: 0 } + const mousePos = this.mousePositions.get(id) || { x: 0, y: 0 }; // Skip rendering if dimensions are invalid if (effect.width <= 0 || effect.height <= 0) { - continue + continue; } // Set canvas size if needed @@ -236,14 +236,14 @@ class GlassEffectManager { this.canvas!.width !== effect.width || this.canvas!.height !== effect.height ) { - this.canvas!.width = effect.width - this.canvas!.height = effect.height - this.gl.viewport(0, 0, effect.width, effect.height) + this.canvas!.width = effect.width; + this.canvas!.height = effect.height; + this.gl.viewport(0, 0, effect.width, effect.height); } // Clear and render - this.gl.clearColor(0, 0, 0, 0) - this.gl.clear(this.gl.COLOR_BUFFER_BIT) + this.gl.clearColor(0, 0, 0, 0); + this.gl.clear(this.gl.COLOR_BUFFER_BIT); // Set uniforms if (this.uniforms.resolution) { @@ -251,58 +251,58 @@ class GlassEffectManager { this.uniforms.resolution, effect.width, effect.height, - ) + ); } if (this.uniforms.time) { - this.gl.uniform1f(this.uniforms.time, currentTime) + this.gl.uniform1f(this.uniforms.time, currentTime); } if (this.uniforms.mouse) { - this.gl.uniform2f(this.uniforms.mouse, mousePos.x, mousePos.y) + this.gl.uniform2f(this.uniforms.mouse, mousePos.x, mousePos.y); } if (this.uniforms.expanded) { this.gl.uniform1f( this.uniforms.expanded, effect.isExpanded ? 1.0 : 0.0, - ) + ); } // Draw - this.gl.drawArrays(this.gl.TRIANGLE_STRIP, 0, 4) + this.gl.drawArrays(this.gl.TRIANGLE_STRIP, 0, 4); // Copy to target canvas - const targetCtx = effect.targetCanvas.getContext("2d") + const targetCtx = effect.targetCanvas.getContext("2d"); if (targetCtx) { - targetCtx.clearRect(0, 0, effect.width, effect.height) - targetCtx.drawImage(this.canvas!, 0, 0) + targetCtx.clearRect(0, 0, effect.width, effect.height); + targetCtx.drawImage(this.canvas!, 0, 0); } } - this.animationFrame = requestAnimationFrame(render) - } + this.animationFrame = requestAnimationFrame(render); + }; - render() + render(); } // Clean up method (optional, for when the app unmounts) destroy() { if (this.animationFrame) { - cancelAnimationFrame(this.animationFrame) + cancelAnimationFrame(this.animationFrame); } if (this.gl && this.program) { - this.gl.deleteProgram(this.program) + this.gl.deleteProgram(this.program); } - this.effects.clear() - this.mousePositions.clear() - GlassEffectManager.instance = null + this.effects.clear(); + this.mousePositions.clear(); + GlassEffectManager.instance = null; } } interface EffectInstance { - id: string - targetCanvas: HTMLCanvasElement - isExpanded: boolean - width: number - height: number + id: string; + targetCanvas: HTMLCanvasElement; + isExpanded: boolean; + width: number; + height: number; } -export default GlassEffectManager +export default GlassEffectManager; |