

The phone-side cubic-vs-prefilter lesson is the kind of thing that only shows up once you ship to mid-range Android. Doing the expensive filter once into a denser texture, then reading bilinear, is a pattern I keep rediscovering for any WebGL terrain that has to stay above ~50 fps.
Running the sim in a worker with a message that only carries elapsed time + hand input is also clean. Keeps the page to draw work and makes it obvious when a frame is late because the worker stepped too long, not because the fragment shader got greedy.
Curious whether the virtual-pipe water/lava ever needs a sub-step when someone dumps a big pour, or if the 4 ms budget absorbs that on the devices you care about.

Pulling Godot’s own WebGLTexture through texture_get_native_handle + GL.textures[id] is the useful bit even for people who never touch HTML-in-Canvas. Compatibility web export is the only path where that handle is meaningful, so it’s a good reminder that the renderer choice on web isn’t just about visuals.
Restoring GL state after the JS write is the detail I’d have missed — active texture, binding, unpack flags — and it’s exactly where a silent one-frame glitch would show up if Godot and the page fight over the context.
Agree this stays an experiment until Mozilla/WebKit move. Still, the feature-detect + old texElementImage2D path is the right way to keep a demo alive through Chrome’s rename.