{"record":{"id":"4f8371597ee0fd7e","repo":"DavidHDev/react-bits","slug":"unable-to-initialize-webgl-render-texture-formats","errorCode":null,"errorMessage":"Unable to initialize WebGL render texture formats.","messagePattern":"Unable to initialize WebGL render texture formats\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"src/ts-default/Animations/SplashCursor/SplashCursor.tsx","lineNumber":180,"sourceCode":"          gl,\n          (gl as WebGL2RenderingContext).RG16F,\n          (gl as WebGL2RenderingContext).RG,\n          halfFloatTexType\n        );\n        formatR = getSupportedFormat(\n          gl,\n          (gl as WebGL2RenderingContext).R16F,\n          (gl as WebGL2RenderingContext).RED,\n          halfFloatTexType\n        );\n      } else {\n        formatRGBA = getSupportedFormat(gl, gl.RGBA, gl.RGBA, halfFloatTexType);\n        formatRG = getSupportedFormat(gl, gl.RGBA, gl.RGBA, halfFloatTexType);\n        formatR = getSupportedFormat(gl, gl.RGBA, gl.RGBA, halfFloatTexType);\n      }\n\n      if (!formatRGBA || !formatRG || !formatR) {\n        throw new Error('Unable to initialize WebGL render texture formats.');\n      }\n\n      return {\n        gl,\n        ext: {\n          formatRGBA,\n          formatRG,\n          formatR,\n          halfFloatTexType,\n          supportLinearFiltering\n        }\n      };\n    }\n\n    function getSupportedFormat(\n      gl: WebGLRenderingContext | WebGL2RenderingContext,\n      internalFormat: number,\n      format: number,","sourceCodeStart":162,"sourceCodeEnd":198,"githubUrl":"https://github.com/DavidHDev/react-bits/blob/c7109dccb42e06592d1d9bc50bc87204697240e2/src/ts-default/Animations/SplashCursor/SplashCursor.tsx#L162-L198","documentation":"After a GL context is acquired, SplashCursor probes whether the GPU can render to half-float textures (RGBA16F/RG16F/R16F) via getSupportedFormat -> supportRenderTextureFormat, which does a texImage2D + framebuffer completeness check. If all probed formats fail framebuffer completeness, getSupportedFormat returns null for at least one of formatRGBA/formatRG/formatR and the fluid sim aborts, because its advection/dye buffers require float render targets.","triggerScenarios":"At src/ts-default/Animations/SplashCursor/SplashCursor.tsx:179-181: formatRGBA, formatRG, or formatR is null after the isWebGL2 branch (lines 159-172) or the webgl1 branch (174-176). Null means the framebuffer for the half-float test was not FRAMEBUFFER_COMPLETE in supportRenderTextureFormat.","commonSituations":"WebGL2 contexts where EXT_color_buffer_float failed to enable (line 142) — common on older mobile GPUs, some Intel integrated chips, and software renderers; WebGL1 paths lacking OES_texture_half_float; drivers that expose the extension but still fail completeness (buggy Mesa/Android drivers); remote-desktop/VM GPU passthrough with limited float support.","solutions":["Ensure a real hardware-accelerated WebGL2 context with EXT_color_buffer_float (check chrome://gpu for the extension).","Update GPU drivers / browser; many older Mesa and Android drivers gained float-render support in later versions.","On dev machines, force discrete GPU (disable power-saving integrated GPU) which usually has float color buffer support.","If unavoidable, degrade gracefully: detect null formats and render a non-fluid static cursor instead of letting the error throw."],"exampleFix":"// before\nif (!formatRGBA || !formatRG || !formatR) {\n  throw new Error('Unable to initialize WebGL render texture formats.');\n}\n\n// after (graceful degradation at the caller)\ntry {\n  const { gl, ext } = getWebGLContext(canvas);\n} catch (e) {\n  if (/render texture formats/.test(String(e))) return null; // fall back to plain cursor\n  throw e;\n}","handlingStrategy":"try-catch","validationCode":"// probe float render-target support without throwing\nfunction supportsFloatRenderTargets(): boolean {\n  const canvas = document.createElement('canvas');\n  const gl = canvas.getContext('webgl2');\n  if (!gl) return false;\n  if (!gl.getExtension('EXT_color_buffer_float')) return false;\n  const tex = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, tex);\n  gl.texImage2D(gl.TEXTURE_2D, 0, gl.R16F, 4, 4, 0, gl.RED, gl.HALF_FLOAT, null);\n  const fbo = gl.createFramebuffer(); gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);\n  gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);\n  return gl.checkFramebufferStatus(gl.FRAMEBUFFER) === gl.FRAMEBUFFER_COMPLETE;\n}","typeGuard":null,"tryCatchPattern":"let ctx;\ntry {\n  ctx = getWebGLContext(canvas);\n} catch (e) {\n  if (e instanceof Error && /render texture formats/.test(e.message)) {\n    return null; // fall back to a non-fluid cursor\n  }\n  throw e;\n}","preventionTips":["Probe EXT_color_buffer_float + framebuffer completeness before mounting SplashCursor.","Prefer hardware-accelerated WebGL2 on discrete GPUs for fluid sims.","Update GPU drivers — older drivers often lack float color buffer support.","Wrap getWebGLContext in try/catch and degrade to a static cursor on failure."],"tags":["webgl2","gpu","float-texture","framebuffer","extension","splashcursor"],"backgroundTag":null,"analyzedSha":"c7109dccb42e06592d1d9bc50bc87204697240e2","analyzedAt":"2026-08-13T02:32:07.327Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}