diff --git a/frontend/src/ShaderBackground.tsx b/frontend/src/ShaderBackground.tsx
index 782c68f..d476a74 100644
--- a/frontend/src/ShaderBackground.tsx
+++ b/frontend/src/ShaderBackground.tsx
@@ -1,5 +1,5 @@
import { useEffect, useRef } from "react";
-import { createAndBindRandomTextureToIChannel0 } from "./randomTextureForShader";
+import { generateRandomRGBABytes } from "./randomTextureForShader";
const buffer_1 = `#version 300 es
precision mediump float;
@@ -964,51 +964,227 @@ export function ShaderBackground() {
}
}
+ const frameBufferTexture = gl.createTexture();
+ if (!frameBufferTexture) return;
+
+ gl.bindTexture(gl.TEXTURE_2D, frameBufferTexture);
+ gl.texImage2D(
+ gl.TEXTURE_2D,
+ 0,
+ gl.RGBA,
+ canvas.width,
+ canvas.height,
+ 0,
+ gl.RGBA,
+ gl.UNSIGNED_BYTE,
+ null
+ );
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+
+ const frameBufferTexture2 = gl.createTexture();
+ if (!frameBufferTexture2) return;
+
+ gl.bindTexture(gl.TEXTURE_2D, frameBufferTexture2);
+ gl.texImage2D(
+ gl.TEXTURE_2D,
+ 0,
+ gl.RGBA,
+ canvas.width,
+ canvas.height,
+ 0,
+ gl.RGBA,
+ gl.UNSIGNED_BYTE,
+ null
+ );
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+
+ const frameBuffer = gl.createFramebuffer();
+ if (!frameBuffer) return;
+
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, frameBuffer);
+
+ gl.framebufferTexture2D(
+ gl.DRAW_FRAMEBUFFER,
+ gl.COLOR_ATTACHMENT0,
+ gl.TEXTURE_2D,
+ frameBufferTexture,
+ 0
+ );
+
+ const status = gl.checkFramebufferStatus(gl.DRAW_FRAMEBUFFER);
+ switch (status) {
+ case gl.FRAMEBUFFER_COMPLETE:
+ console.log("Framebuffer is complete");
+ break;
+ case gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
+ console.log("Framebuffer is incomplete attachment");
+ break;
+ case gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
+ console.log("Framebuffer is incomplete missing attachment");
+ break;
+ case gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
+ console.log("Framebuffer is incomplete dimensions");
+ break;
+ case gl.FRAMEBUFFER_UNSUPPORTED:
+ console.log("Framebuffer is unsupported");
+ break;
+ default:
+ console.log("Framebuffer is unknown");
+ }
+
+ const posBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, posBuffer);
+ gl.bufferData(
+ gl.ARRAY_BUFFER,
+ new Float32Array([0, 0, 1, 0, 0, 1, 1, 1]),
+ gl.STATIC_DRAW
+ );
+
+ const ichannel0_location_buffer_1 = gl.getUniformLocation(
+ buffer_1_program as WebGLProgram,
+ "iChannel0"
+ );
+
+ const ichannel0_location_buffer_2 = gl.getUniformLocation(
+ buffer_2_program as WebGLProgram,
+ "iChannel0"
+ );
+
+ const ichannel0_location_buffer_3 = gl.getUniformLocation(
+ buffer_3_program as WebGLProgram,
+ "iChannel0"
+ );
+
+ const ichannel0_location_buffer_4 = gl.getUniformLocation(
+ buffer_4_program as WebGLProgram,
+ "iChannel0"
+ );
+
+ const ichannel0_location_final = gl.getUniformLocation(
+ finalProgram as WebGLProgram,
+ "iChannel0"
+ );
+
function render(
gl: WebGL2RenderingContext,
canvas: HTMLCanvasElement,
now: number
) {
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, frameBuffer);
+
//Clear with Clear color
gl.clear(gl.COLOR_BUFFER_BIT);
gl.useProgram(buffer_1_program);
setResolution(buffer_1_program as WebGLProgram, canvas, gl);
setTime(buffer_1_program as WebGLProgram, now, gl);
- const tex = createAndBindRandomTextureToIChannel0(
- gl,
- buffer_1_program as WebGLProgram,
- canvas.width,
- canvas.height
- );
+ const bytes = generateRandomRGBABytes(canvas.width, canvas.height);
+
+ const tex = gl.createTexture();
+ if (!tex) throw new Error("Failed to create texture");
+
+ // Activate texture unit 0 and bind the texture
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, tex);
+ // Texture parameters suitable for data textures
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+
+ // Upload pixel data as RGBA UNSIGNED_BYTE
+ gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
+ gl.texImage2D(
+ gl.TEXTURE_2D,
+ 0,
+ gl.RGBA,
+ canvas.width,
+ canvas.height,
+ 0,
+ gl.RGBA,
+ gl.UNSIGNED_BYTE,
+ bytes
+ );
+
+ // Set sampler uniform to texture unit 0
+ gl.uniform1i(ichannel0_location_buffer_1, 0);
+
// RENDER 1
- gl.drawBuffers([gl.BACK]);
+ gl.framebufferTexture2D(
+ gl.DRAW_FRAMEBUFFER,
+ gl.COLOR_ATTACHMENT0,
+ gl.TEXTURE_2D,
+ frameBufferTexture,
+ 0
+ );
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
gl.useProgram(buffer_2_program);
setResolution(buffer_2_program as WebGLProgram, canvas, gl);
// RENDER 2
- gl.drawBuffers([gl.BACK]);
+ gl.activeTexture(gl.TEXTURE1);
+ gl.bindTexture(gl.TEXTURE_2D, frameBufferTexture);
+ gl.uniform1i(ichannel0_location_buffer_2, 1);
+ gl.framebufferTexture2D(
+ gl.DRAW_FRAMEBUFFER,
+ gl.COLOR_ATTACHMENT0,
+ gl.TEXTURE_2D,
+ frameBufferTexture2,
+ 0
+ );
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
gl.useProgram(buffer_3_program);
setResolution(buffer_3_program as WebGLProgram, canvas, gl);
// RENDER 3
- gl.drawBuffers([gl.BACK]);
+ gl.activeTexture(gl.TEXTURE1);
+ gl.bindTexture(gl.TEXTURE_2D, frameBufferTexture2);
+ gl.uniform1i(ichannel0_location_buffer_3, 1);
+ gl.framebufferTexture2D(
+ gl.DRAW_FRAMEBUFFER,
+ gl.COLOR_ATTACHMENT0,
+ gl.TEXTURE_2D,
+ frameBufferTexture,
+ 0
+ );
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
gl.useProgram(buffer_4_program);
setResolution(buffer_4_program as WebGLProgram, canvas, gl);
// RENDER 4
- gl.drawBuffers([gl.BACK]);
+ gl.activeTexture(gl.TEXTURE1);
+ gl.bindTexture(gl.TEXTURE_2D, frameBufferTexture);
+ gl.uniform1i(ichannel0_location_buffer_4, 1);
+ gl.framebufferTexture2D(
+ gl.DRAW_FRAMEBUFFER,
+ gl.COLOR_ATTACHMENT0,
+ gl.TEXTURE_2D,
+ frameBufferTexture2,
+ 0
+ );
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
gl.useProgram(finalProgram);
setResolution(finalProgram as WebGLProgram, canvas, gl);
// FINAL RENDER
+ gl.activeTexture(gl.TEXTURE1);
+ gl.bindTexture(gl.TEXTURE_2D, frameBufferTexture2);
+ gl.uniform1i(ichannel0_location_final, 1);
+ gl.framebufferTexture2D(
+ gl.DRAW_FRAMEBUFFER,
+ gl.COLOR_ATTACHMENT0,
+ gl.TEXTURE_2D,
+ frameBufferTexture,
+ 0
+ );
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);
gl.drawArrays(gl.TRIANGLES, 0, 6);
}
@@ -1024,5 +1200,7 @@ export function ShaderBackground() {
requestAnimationFrame(update);
}, []);
- return ;
+ return (
+
+ );
}
diff --git a/frontend/src/randomTextureForShader.ts b/frontend/src/randomTextureForShader.ts
index 60d133a..57cc139 100644
--- a/frontend/src/randomTextureForShader.ts
+++ b/frontend/src/randomTextureForShader.ts
@@ -33,61 +33,3 @@ export function generateRandomRGBABytes(
return out;
}
-
-/**
- * Create a WebGL texture from random data and bind it to texture unit 0,
- * then set the sampler2D uniform named `iChannel0` to use unit 0.
- *
- * gl: WebGLRenderingContext or WebGL2RenderingContext
- * program: compiled & linked shader program (must be in use or will be used)
- */
-export function createAndBindRandomTextureToIChannel0(
- gl: WebGLRenderingContext | WebGL2RenderingContext,
- program: WebGLProgram,
- width: number,
- height: number
-): WebGLTexture {
- const bytes = generateRandomRGBABytes(width, height);
-
- const tex = gl.createTexture();
- if (!tex) throw new Error("Failed to create texture");
-
- // Activate texture unit 0 and bind the texture
- gl.activeTexture(gl.TEXTURE0);
- gl.bindTexture(gl.TEXTURE_2D, tex);
-
- // Texture parameters suitable for data textures
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
-
- // Upload pixel data as RGBA UNSIGNED_BYTE
- gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
- gl.texImage2D(
- gl.TEXTURE_2D,
- 0,
- gl.RGBA,
- width,
- height,
- 0,
- gl.RGBA,
- gl.UNSIGNED_BYTE,
- bytes
- );
-
- const location = gl.getUniformLocation(program, "iChannel0");
- if (location === null) {
- // Clean up binding and return but signal with thrown error if desired
- gl.bindTexture(gl.TEXTURE_2D, null);
- throw new Error("Uniform 'iChannel0' not found in program");
- }
-
- // Set sampler uniform to texture unit 0
- gl.uniform1i(location, 0);
-
- // Unbind the texture if you prefer (not strictly necessary)
- gl.bindTexture(gl.TEXTURE_2D, null);
-
- return tex;
-}