{"record":{"id":"d8084112e0394959","repo":"MiniMax-AI/skills","slug":"webgl2-not-supported","errorCode":null,"errorMessage":"WebGL2 not supported","messagePattern":"WebGL2 not supported","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"skills/shader-dev/techniques/fluid-simulation.md","lineNumber":113,"sourceCode":"gl.uniform4f(uMouse, iMouse[0], iMouse[1], iMouse[2], 0.0);\n// IMPORTANT: Mouse velocity must be clamped, otherwise fast dragging produces huge velocity deltas causing NaN explosion\nconst mvx = Math.max(-50, Math.min(50, iMouse[0] - prevMouse[0]));\nconst mvy = Math.max(-50, Math.min(50, iMouse[1] - prevMouse[1]));\ngl.uniform2f(uMouseVel, mvx, mvy);\n```\n\n### Handling WebGL 2 Unavailability\n\n```javascript\nconst gl = canvas.getContext(\"webgl2\");\nif (!gl) {\n    document.body.innerHTML = `\n        <div style=\"color:#fff;padding:20px;font-family:sans-serif;\">\n            <h2>WebGL 2 Not Supported</h2>\n            <p>Fluid simulation requires WebGL 2. Please use a modern browser (Chrome 56+, Firefox 51+, Safari 15+).</p>\n        </div>\n    `;\n    throw new Error('WebGL2 not supported');\n}\n```\n\n# Real-Time Fluid Simulation\n\n## Use Cases\n- Real-time 2D fluid effects in ShaderToy/WebGL (smoke, liquids, ink diffusion)\n- Interactive fluid: mouse/touch-driven fluid response\n- **Ink diffusion/curling vortex effects in water**: vorticity confinement + high diffusion coefficient + single or multi-color ink\n- **Multi-color ink mixing**: multiple ink colors interpenetrating and blending (requires Buffer B to store RGB ink, see multi-color ink mixing template)\n- Decorative fluid backgrounds, particle systems, vortex visualization\n- **Lava/fire/magma effects**: fluid simulation + FBM noise texture + temperature color mapping\n- **Water surface ripple effects**: wave equation + click-generated concentric ripples + interference and damping\n- Core: solving simplified Navier-Stokes equations or wave equations in GPU fragment shaders\n\n## Core Principles\n\nIncompressible Navier-Stokes equation discretization:","sourceCodeStart":95,"sourceCodeEnd":131,"githubUrl":"https://github.com/MiniMax-AI/skills/blob/60aaae52bb2af8162732751a4332f62a5fef518b/skills/shader-dev/techniques/fluid-simulation.md#L95-L131","documentation":"`throw new Error('WebGL2 not supported')` in the fluid-simulation technique doc after `canvas.getContext(\"webgl2\")` returns null. `getContext` yields null (rather than throwing) when the browser cannot provide a WebGL2 context. The technique first injects a fallback HTML message, then throws so dependent simulation init never runs on an incapable browser.","triggerScenarios":"Running the page in a browser/GPU combo without WebGL2: older Safari (<15), a blacklisted GPU/driver, hardware acceleration disabled in the browser settings, a headless or software-rendered environment, or the context being lost/exhausted.","commonSituations":"Testing in an old Safari, running in a VM/CI without GPU acceleration, users with hardware acceleration turned off, or devices with denylisted graphics drivers.","solutions":["Use a WebGL2-capable browser: Chrome 56+, Firefox 51+, or Safari 15+.","Enable hardware acceleration in the browser settings and update GPU drivers.","For headless/CI, run with a software GL implementation (e.g. SwiftShader) or skip the GL code path.","Guard the entry point and show a graceful fallback rather than letting the throw crash the page."],"exampleFix":"// before\nconst gl = canvas.getContext(\"webgl2\");\nif (!gl) { document.body.innerHTML = fallback; throw new Error('WebGL2 not supported'); }\n\n// after — degrade gracefully without throwing\nconst gl = canvas.getContext(\"webgl2\");\nif (!gl) { renderStaticFallback(); return; }\nstartSimulation(gl);","handlingStrategy":"fallback","validationCode":"const gl = canvas.getContext('webgl2');\nif (!gl) {\n  // capability check before any GL work\n  renderStaticFallback();\n  return; // do NOT throw\n}","typeGuard":"function supportsWebGL2(): boolean {\n  try {\n    const c = document.createElement('canvas');\n    return !!c.getContext('webgl2');\n  } catch { return false; }\n}","tryCatchPattern":"try {\n  const gl = canvas.getContext('webgl2');\n  if (!gl) throw new Error('WebGL2 not supported');\n  startSimulation(gl);\n} catch (e) {\n  if (e instanceof Error && /WebGL2/i.test(e.message)) {\n    renderStaticFallback();\n  } else throw e;\n}","preventionTips":["Run a capability check on app load and gate the GL code path behind it.","Detect the official blocklist via `gl.getExtension('WEBGL_debug_renderer_info')` to warn on known-bad drivers.","Provide a non-GL fallback so unsupported users still see content.","Test in a software-rendered/headless mode during CI to catch context-creation regressions."],"tags":["webgl","webgl2","browser","gpu","fluid-simulation","javascript"],"backgroundTag":null,"analyzedSha":"60aaae52bb2af8162732751a4332f62a5fef518b","analyzedAt":"2026-08-13T17:32:34.717Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}