[HN Gopher] Show HN: Box2D fluid simulation in WebGL and WASM
       ___________________________________________________________________
        
       Show HN: Box2D fluid simulation in WebGL and WASM
        
       Author : Birch-san
       Score  : 33 points
       Date   : 2021-04-02 18:32 UTC (4 hours ago)
        
 (HTM) web link (birchlabs.co.uk)
 (TXT) w3m dump (birchlabs.co.uk)
        
       | boogies wrote:
       | Does this work for most people? I'd assume it was just my
       | slightly out of date version of the weird browser Palemoon that
       | makes it throw "SyntaxError: missing declaration after 'import'
       | keyword" and stay blank white (https://ibb.co/Bj2HHxH) for me,
       | but a dead comment just claimed it's broken on both macOS and iOS
       | Safari, and Chrome.
        
         | stevenpetryk wrote:
         | Works only in Chromium for me, not Safari or Firefox. But it's
         | just a technical demo so, meh.
        
         | Birch-san wrote:
         | Ah, if it's blank, then it blew up really early.
         | 
         | It sounds like it's complaining about the use of ES modules.
         | This script is loaded with `<script type="module">` and uses ES
         | imports (`import App from './App.svelte'`).
         | 
         | Yes, Safari is expected to go bang (doesn't support module
         | Workers).
         | 
         | I target Chromium's featureset -- I developed on macOS Edge.
         | macOS Chrome and Android's Chrome WebView work for me too.
         | 
         | It needs a few modern features in order to work:
         | - Web workers       - WebAssembly       - top-level await (on
         | Web, and in Worker)       - ES modules + imports (on Web, and
         | in Worker)       - requestAnimationFrame in Worker       -
         | WebGL2       - OffscreenCanvas
         | 
         | Most of these were chosen for "ease of development". With
         | bundling, it'd be possible to eliminate the ES modules / await
         | usage. WebGL2 isn't strictly necessary either. WASM + workers
         | are widely supported.
         | 
         | So the primary blocker to Firefox support is support for
         | OffscreenCanvas, and requestAnimationFrame in Worker. There's
         | other options there: render on the main thread instead. Harder
         | to develop (syncing timing + state between threads). Can
         | probably be done performantly with SharedArrayBuffer.
         | 
         | In truth, I did include error-handling to provide a
         | compatibility explanation if the worker explodes. This displays
         | in Firefox. But I hadn't expected the main thread to explode
         | too.
         | 
         | Here's a GIF of what it's supposed to look like!
         | 
         | https://birchlabs.co.uk/box2d-wasm-liquidfun/liquidfun.gif
        
       | [deleted]
        
       | LinguaBrowse wrote:
       | Nice work!
       | 
       | What's the benefit of using WebGL compared to Canvas?
       | 
       | Does the WASM bring a performance improvement in practice,
       | relative to the equivalent JS library?
       | 
       | Keep it up!
        
         | stevenpetryk wrote:
         | You can write vertex shaders in WebGL to massively parallelize
         | calculating the movement of each particle. This isn't possible
         | in canvas.
         | 
         | And that just optimizes the physics--there's even more
         | parallelization with the actual drawing! Drawing a bunch of
         | points like this can be achieved using a single fragment shader
         | that takes a big array of positions. Drawing new positions
         | involves just copying the array of positions from the CPU to
         | the GPU.
         | 
         | But if you're using both vertex and fragment shaders, the GPU
         | might entirely handle updating and drawing points over time
         | (and thus can be parallelized across hundreds of cores), only
         | needing the CPU to set up the initial point positions and get
         | things started.
         | 
         | With canvas, all the work (including rendering each frame)
         | takes the JS main thread, running on the CPU.
         | 
         | Here's a cool demo of how much better WebGL is at rendering a
         | ton of 2D sprites! Be careful turning up the number of sprites
         | with canvas--it might lock up your main thread and be difficult
         | to undo.
         | 
         | https://bl.ocks.org/DevAndyLee/raw/a901617de28912b1e3cbdc6e8...
        
           | moron4hire wrote:
           | They aren't doing the particle sim in WebGL. That's the WASM
           | part.
           | 
           | As an aside: there are new standards in the works for getting
           | even the CanvasContext2D rendering off of the main thread. On
           | an HTMLCanvasElement, you can call
           | transferControlToOffscreen(), which will retrun an
           | OffscreenCanvas object. That object can then be transfered to
           | a Worker. From there, you can create the 2D rendering context
           | (make sure you don't create any 2D contexts on that canvas in
           | the main thread) and draw to the canvas in the worker (you
           | can do this for WebGL contexts, as well).
           | 
           | All the drawing ops performed on the OffscreenCanvas will
           | appear in the HTMLCanvasElement immediately, without having
           | to perform a callback message from the Worker back to the
           | main thread.
           | 
           | https://developer.mozilla.org/en-
           | US/docs/Web/API/OffscreenCa...
           | 
           | Unfortunately, OffscreenCanvas is still in development in
           | Firefox, only accessible behind a flag. In my testing with
           | the feature enabled, it also seems that Mozilla hasn't
           | implemented 2D contexts in Workers, only having the WebGL
           | context available, which is quite annoying.
           | 
           | I don't know the status in Safari, but Apple has historically
           | been very slow about implementing new features.
        
             | stevenpetryk wrote:
             | Yeah, I didn't know the specifics of this sim, I just
             | wanted to clarify the advantages of WebGL for even 2D
             | stuff.
             | 
             | The OffscreenCanvas thing sounds awesome! I still think it
             | might be slower because you can't utilize shaders... but
             | I'm sure we'll get there.
        
               | moron4hire wrote:
               | Yes, that is definitely true.
               | 
               | I use it for text rendering, myself. Getting text
               | rendering working in shader code is pretty difficult and
               | gives pretty low quality results. You have to create a
               | glyph map for all the characters you plan to render--
               | which also means you have to plan ahead of time what text
               | you're going to render--and you are stuck with only one
               | color for all of the text (there are some multicolor SDF-
               | based systems, but they aren't very common).
               | 
               | So I render the text in a 2D rendering context, with all
               | the fancy bells and whistles and support for changing
               | fonts on the fly and colors and transformations and a
               | sane API, in a Worker, save off an ImageBitmap object
               | from it, transfer that ImageBitmap back to the main
               | thread, and use it as a texture on 3D geometry.
               | 
               | I also use 3D contexts in Workers to do some pre-
               | processing on textures, like converting equirectangular
               | skymaps into rectalinear cubemaps. The worker is setup to
               | be able to preload these images while the user is doing
               | other things, then transfer the results when they are
               | needed during a scene transition, so the scene transition
               | is nearly instanteous.
        
       | singularity2001 wrote:
       | Doesn't work on Firefox
       | 
       | SyntaxError: import declarations may only appear at top level of
       | a module
        
       | Y_Y wrote:
       | How come only Chrome has whatever feature this needs?
        
         | paulgb wrote:
         | GPU on the web is unfortunately kind of fragmented at the
         | moment. WebGL 1 has pretty broad support but has some technical
         | limitations; WebGL 2 (which this uses) is supported in most
         | things but not (stable) Safari or iOS-based browsers[1]. WebGPU
         | is apparently around the corner but it will likely be years
         | before it has broad support.
         | 
         | (I see reports here of it also not working on Firefox, which
         | must be another reason, as FF does support WebGL2 and
         | WebAssembly.)
         | 
         | [1] https://caniuse.com/webgl2
        
           | hwillis wrote:
           | God damn I can't wait for webGPU. I would really, _really_
           | like to have geometry stages, compute shaders, RTX, and
           | actual vulkan-style commands, but that 's a little too much
           | to ask of browsers. Too many kinds of hardware, even if you
           | pass device checks onto the developer (which they still
           | should).
           | 
           | 60 second explanation of the three APIs:
           | 
           | WebGL 1: vertices and triangles are stored on the global GL
           | context object and need to be rebuilt every frame. Shader
           | language is a very goofy, somewhat obnoxious GLSL lookalike.
           | You can write vertex and fragment shaders, which are the
           | necessary ones to render, but also the least interesting.
           | Post-processing is a _serious_ pain. FPS is limited by
           | bandwidth to submit to the GPU and CPU usage can be _stupid_
           | high.
           | 
           | WebGL 2: improved shader language (much more similar to GLSL,
           | better compilation, better branching), still only two
           | pipeline stages. Render buffers, depth buffers, multidraw,
           | allowing for modern techniques like deferred rendering and
           | efficient shadowmaps. Vertex attribute buffers are their own
           | thing amd dont have to be freshened for every draw call. At
           | this point webGL is similar-ish to native opengl with a bunch
           | of missing features. In webGL 1 you had to do things very
           | differently from a native api, which was very slow, messy,
           | and annoying.
           | 
           | WebGPU:Vulkan came out! And everyone learned that oh,
           | actually having everything on a single thread really sucks,
           | huh. OpenGL has a global context that prevents great
           | threading- have to make draws from a single thread, even if
           | you can construct buffers etc in job threads (minor
           | improvement) you have to sync back. Vulkan and webGPU let you
           | submit to command buffers with their own contexts. In WebGL 1
           | you had to rebuild and rebind all of an object's vertices
           | every time it had a drawcall. In WebGL 2 you built them once
           | and just have to rebind each one in series for every frame.
           | In WebGPU, you can bind in parallel from webworkers. Not
           | ideal parallelism, but shockingly good for javascript. For
           | some things like shaders, you don't even need to recompile,
           | which is a hard-to-avoid main thread blocker in WebGL 1/2.
           | 
           | WebGPU can also do compute, which _rules_ - many complex AAA
           | techniques really require this and don't work on WebGL
           | because it wants to send all its render buffers back to the
           | CPU.
        
         | nitrogen wrote:
         | Current Firefox shows this error in the page: _SyntaxError:
         | import declarations may only appear at top level of a module_
        
       | FriendlyNormie wrote:
       | Your dogshit experiment doesn't work, asshole. Doesn't load on
       | Safari on neither a Mac nor an iPhone, and on Chrome it just
       | shows a blank white box and some javascript errors. The browser
       | it's "supposed" to work on. Jesus. Fuck you and your worthless
       | dogshit. If I wanted to relive the experience of wrestling with
       | experimental garbage websites that don't work then I'd go back to
       | 1999 and try to use sites with embedded Java applets. FUCK YOU.
        
       ___________________________________________________________________
       (page generated 2021-04-02 23:00 UTC)