From e579ae120290329fd697b50ea9138ffccb65a805 Mon Sep 17 00:00:00 2001 From: Maze Winther Date: Wed, 1 Apr 2026 13:57:32 +0200 Subject: feat: migrate GPU renderer from WebGL to wgpu/WASM --- apps/web/src/services/renderer/webgl/jfa.ts | 194 ---------------------------- 1 file changed, 194 deletions(-) delete mode 100644 apps/web/src/services/renderer/webgl/jfa.ts (limited to 'apps/web/src/services/renderer/webgl/jfa.ts') diff --git a/apps/web/src/services/renderer/webgl/jfa.ts b/apps/web/src/services/renderer/webgl/jfa.ts deleted file mode 100644 index 9c87e7fa..00000000 --- a/apps/web/src/services/renderer/webgl/jfa.ts +++ /dev/null @@ -1,194 +0,0 @@ -import jfaInitShader from "@/lib/shaders/jfa-init.frag.glsl"; -import jfaStepShader from "@/lib/shaders/jfa-step.frag.glsl"; -import { - compileProgram, - createFramebufferTexture, - setUniforms, - drawFullscreenQuad, -} from "./webgl-utils"; - -interface FBPair { - texture: WebGLTexture; - framebuffer: WebGLFramebuffer; -} - -function runPass({ - context, - program, - inputTexture, - target, - width, - height, - uniforms, - extraBindings, -}: { - context: WebGLRenderingContext; - program: WebGLProgram; - inputTexture: WebGLTexture; - target: WebGLFramebuffer | null; - width: number; - height: number; - uniforms: Record; - extraBindings?: Array<{ unit: number; texture: WebGLTexture; name: string }>; -}): void { - context.bindFramebuffer(context.FRAMEBUFFER, target); - // biome-ignore lint/correctness/useHookAtTopLevel: WebGL API method, not a React hook - context.useProgram(program); - - context.activeTexture(context.TEXTURE0); - context.bindTexture(context.TEXTURE_2D, inputTexture); - const uTexLoc = context.getUniformLocation(program, "u_texture"); - if (uTexLoc) context.uniform1i(uTexLoc, 0); - - if (extraBindings) { - for (const binding of extraBindings) { - context.activeTexture(context.TEXTURE0 + binding.unit); - context.bindTexture(context.TEXTURE_2D, binding.texture); - const loc = context.getUniformLocation(program, binding.name); - if (loc) context.uniform1i(loc, binding.unit); - } - } - - setUniforms({ - context, - program, - uniforms: { ...uniforms, u_resolution: [width, height] }, - }); - drawFullscreenQuad({ context, program, width, height }); -} - -function runJFA({ - context, - programCache, - sourceTexture, - width, - height, - isInverted, -}: { - context: WebGLRenderingContext; - programCache: Map; - sourceTexture: WebGLTexture; - width: number; - height: number; - isInverted: boolean; -}): { - resultTexture: WebGLTexture; - resultFB: WebGLFramebuffer; - tempFBs: FBPair[]; -} { - const numSteps = Math.ceil(Math.log2(Math.max(width, height))); - - const fbA = createFramebufferTexture({ context, width, height }); - const fbB = createFramebufferTexture({ context, width, height }); - - const initProgram = compileProgram({ - context, - fragmentShaderSource: jfaInitShader, - programCache, - }); - runPass({ - context, - program: initProgram, - inputTexture: sourceTexture, - target: fbA.framebuffer, - width, - height, - uniforms: { u_invert: isInverted ? 1.0 : 0.0 }, - }); - - const stepProgram = compileProgram({ - context, - fragmentShaderSource: jfaStepShader, - programCache, - }); - - let readFB = fbA; - let writeFB = fbB; - - for (let i = numSteps - 1; i >= 0; i--) { - const stepSize = 2 ** i; - runPass({ - context, - program: stepProgram, - inputTexture: readFB.texture, - target: writeFB.framebuffer, - width, - height, - uniforms: { u_step_size: stepSize }, - }); - const tmp = readFB; - readFB = writeFB; - writeFB = tmp; - } - - return { - resultTexture: readFB.texture, - resultFB: readFB.framebuffer, - tempFBs: [writeFB], - }; -} - -function cleanupJFAResult({ - context, - result, -}: { - context: WebGLRenderingContext; - result: { - resultTexture: WebGLTexture; - resultFB: WebGLFramebuffer; - tempFBs: FBPair[]; - }; -}): void { - context.deleteTexture(result.resultTexture); - context.deleteFramebuffer(result.resultFB); - for (const fb of result.tempFBs) { - context.deleteTexture(fb.texture); - context.deleteFramebuffer(fb.framebuffer); - } -} - -export { runPass }; - -export function computeSignedDistanceField({ - context, - programCache, - sourceTexture, - width, - height, -}: { - context: WebGLRenderingContext; - programCache: Map; - sourceTexture: WebGLTexture; - width: number; - height: number; -}): { - insideTexture: WebGLTexture; - outsideTexture: WebGLTexture; - cleanup: () => void; -} { - const inside = runJFA({ - context, - programCache, - sourceTexture, - width, - height, - isInverted: false, - }); - const outside = runJFA({ - context, - programCache, - sourceTexture, - width, - height, - isInverted: true, - }); - - return { - insideTexture: inside.resultTexture, - outsideTexture: outside.resultTexture, - cleanup: () => { - cleanupJFAResult({ context, result: inside }); - cleanupJFAResult({ context, result: outside }); - }, - }; -} -- cgit v1.3.1