export function generateRandomRGBABytes( width: number, height: number ): Uint8Array { if (width <= 0 || height <= 0) { throw new Error("width and height must be positive"); } const len = width * height * 4; const out = new Uint8Array(len); // Maximum bytes per getRandomValues call (per spec / browsers) const MAX_GETRANDOM_BYTES = 65536; if (typeof crypto !== "undefined" && "getRandomValues" in crypto) { // Fill in chunks of up to MAX_GETRANDOM_BYTES let offset = 0; while (offset < len) { const chunkSize = Math.min(MAX_GETRANDOM_BYTES, len - offset); // Subarray view for the current chunk const chunkView = out.subarray(offset, offset + chunkSize); crypto.getRandomValues(chunkView); offset += chunkSize; } // Ensure alpha channel is fully opaque (255) for (let i = 3; i < len; i += 4) out[i] = 255; } else { // Fallback to Math.random for all bytes for (let i = 0; i < len; i++) { if ((i + 1) % 4 === 0) out[i] = 255; else out[i] = Math.floor(Math.random() * 256); } } 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; }