In my experience the web is a huge pain in the butt. But since it's there (and its convenient for distribution) it is an expected target for an engine like this.
But really the problems that I've experienced are:
- de facto tooling (Emscripten) is very immature and poorly documented. Everything "just works" when it doesn't or when it "works" the semantics are completely different. For example async file APIs. Every update of Emscripten breaks something.
- The Web has nerfed a lot of APIs. For example to use "threads" aka web workers you need SharedArrayBuffers and for those you need to enable several web policies. A massive deployment pain.
- The Web APIs are often poorly thought out such as pointer locking. Why can't I just hide my cursor when it's on some particular element? LockPointerSendEmailToMom type of situation here. Full screen APIs, audio context uh uh.. and to make things worse every browser has its own quirks.
- The Web APIs have tremendous performance degradation compared to running native. Your rendering calls must be optimized. Your unoptimized code might run natively at 2000 fps but when you run in WASM against WebGL you'll have hick-ups at 60fps.
- Timing is hard, RAF really sucks and you have continuous little delta jitters that cause micro stutter.
- WASM raw performance might be okay-ish but by itself it's useless because you need to interact with the APIs such as WebGL, WebAudio etc. to make anything actually useful. Keep in mind every WebGL probably executes around 1m lines of code at least and does several IPC handoffs to get to the browsers rendering / GPU process (in chrome). Heck, native audio buffers 20ms are fine, on the web though... you'll need more like +100ms. Terrible.
Bonus tip, if you're on Emscripten definitely don't bother with their OpenAL audio api. I'd recommend to use WebAudio. Sokol has a pretty workable wrapper for that.
The overhead of the WASM <-> JS bridge per call remains utterly insane, and this is the root of a lot of the pain. Whenever I found myself profiling it I start thinking I'm missing something, then found that this is what everyone learns the hard way. This is why I have yet to deploy anything that does much WASM physics, since physics engines generate a lot of callbacks by default. (I spent a lot of my life dealing with things like the JNI or early Unity, and nothing compares to the WASM overhead at all).
The timing "for security" drives me insane too, especially how different it is across browsers.
I resorted to having a worker that does everything except make the actual web API calls, and that's what is going on at https://luduxia.com/whichwayround
Actually in my experience running physics (Box2D) is relatively harmless since it's purely in WASM and doesn't need to interact with any JS API directly.
By far the biggest headache for me is actually Lua. It has terrible perf natively also but in WASM it's complete dog shit. I suspect there might be some bad allocation patterns or something that make it perform very poorly. I haven't had time to investigate that yet to my satisfaction.
Your game runs quite smoothly, didn't get the logic but it didn't jank much. :)
> Actually in my experience running physics (Box2D) is relatively harmless since it's purely in WASM and doesn't need to interact with any JS API directly.
I see! In my case the actual scene graph is in JS too, and I've seen enough people struggle with both approaches to wonder which one really comes out ahead in the end.
> Your game runs quite smoothly, didn't get the logic but it didn't jank much. :)
Good! These assets here are not remotely optimal, but the core loop going on is not too bad given the complexity of what it can through around before having problems.
The whole separate worker thing introduces inevitable continuous timing problems, but I've seen too many webgl games where they run perfectly smoothly for a bit, then stutter like hell, and repeat. It's got to be GC gunk.
The sad thing is that most of these issues have been around for a decade or more, and it feels like very little progress has been made aside from WebGPU almost being usable now (still waiting for Safari and Firefox). Unreal Engine had a web target, again a decade ago, and ended up deprecating it because such little progress had been made in maturing the platform.
I think a lot of these issues are simply unsolvable given the current web infrastructure and the way everything is designed against adversarial programs. Like nerfing the APIs, IPC handoffs and such. The only GPU workload that works well here is something that is nearly completely static, does nothing much than a single draw call and everything else is statically allocated and never changed.
Essentially shadertoy (+ a bunch of similar demos)
Edit: Must be a schizophrenic feeling to design Web APIs where you first design functionality that is useful for the web apps and then you find ways to amputate that functionality in the name of security.
WebGPU is a big step in the right direction for graphics but that's another place where progress has been glacially slow. I think the initiative started in 2016, it took until 2023 for Chrome to ship it, and Apple are still dragging their feet heading into 2025. WebGL was already severely dated at the start of that process and we're still stuck with WebGL for portable web graphics to this day!
There were several console prototypes targeting HTML5 games over ten years ago, based mainly on the results of early emscripten work. It generated a lot of noise in some circles.
Obviously they dissolved/morphed into quite different things.
Wow, cool! Have any playable games been made with Castle?
I loved spending some time with Delphi when I was learning to program. What’s the state of Pascal these days?
Edit: I see they have a gallery of games some of which are published on Steam and on the Switch: https://castle-engine.io/gallery_games.php
Good luck to you.
In my experience the web is a huge pain in the butt. But since it's there (and its convenient for distribution) it is an expected target for an engine like this.
But really the problems that I've experienced are:
Bonus tip, if you're on Emscripten definitely don't bother with their OpenAL audio api. I'd recommend to use WebAudio. Sokol has a pretty workable wrapper for that.Source for all this:
https://github.com/ensisoft/detonator
So much annoying truth there.
The overhead of the WASM <-> JS bridge per call remains utterly insane, and this is the root of a lot of the pain. Whenever I found myself profiling it I start thinking I'm missing something, then found that this is what everyone learns the hard way. This is why I have yet to deploy anything that does much WASM physics, since physics engines generate a lot of callbacks by default. (I spent a lot of my life dealing with things like the JNI or early Unity, and nothing compares to the WASM overhead at all).
The timing "for security" drives me insane too, especially how different it is across browsers.
I resorted to having a worker that does everything except make the actual web API calls, and that's what is going on at https://luduxia.com/whichwayround
Actually in my experience running physics (Box2D) is relatively harmless since it's purely in WASM and doesn't need to interact with any JS API directly.
By far the biggest headache for me is actually Lua. It has terrible perf natively also but in WASM it's complete dog shit. I suspect there might be some bad allocation patterns or something that make it perform very poorly. I haven't had time to investigate that yet to my satisfaction.
Your game runs quite smoothly, didn't get the logic but it didn't jank much. :)
> Actually in my experience running physics (Box2D) is relatively harmless since it's purely in WASM and doesn't need to interact with any JS API directly.
I see! In my case the actual scene graph is in JS too, and I've seen enough people struggle with both approaches to wonder which one really comes out ahead in the end.
> Your game runs quite smoothly, didn't get the logic but it didn't jank much. :)
Good! These assets here are not remotely optimal, but the core loop going on is not too bad given the complexity of what it can through around before having problems.
The whole separate worker thing introduces inevitable continuous timing problems, but I've seen too many webgl games where they run perfectly smoothly for a bit, then stutter like hell, and repeat. It's got to be GC gunk.
Here's an example of running Box2D physics in WASM
https://ensisoft.com/demos/playground/game.html
Still very small scenes of course so not much stuff going on. Yes, the GC pauses are a known issue in Lua.
The sad thing is that most of these issues have been around for a decade or more, and it feels like very little progress has been made aside from WebGPU almost being usable now (still waiting for Safari and Firefox). Unreal Engine had a web target, again a decade ago, and ended up deprecating it because such little progress had been made in maturing the platform.
I think a lot of these issues are simply unsolvable given the current web infrastructure and the way everything is designed against adversarial programs. Like nerfing the APIs, IPC handoffs and such. The only GPU workload that works well here is something that is nearly completely static, does nothing much than a single draw call and everything else is statically allocated and never changed.
Essentially shadertoy (+ a bunch of similar demos)
Edit: Must be a schizophrenic feeling to design Web APIs where you first design functionality that is useful for the web apps and then you find ways to amputate that functionality in the name of security.
WebGPU is a big step in the right direction for graphics but that's another place where progress has been glacially slow. I think the initiative started in 2016, it took until 2023 for Chrome to ship it, and Apple are still dragging their feet heading into 2025. WebGL was already severely dated at the start of that process and we're still stuck with WebGL for portable web graphics to this day!
Honestly, WebGPU once available will become a total security disaster area, and that is contributing to the foot dragging.
What was/is needed is a WebGL 2.5 that enables async access to the GL context.
Arguably both of them should require permissions.
There were several console prototypes targeting HTML5 games over ten years ago, based mainly on the results of early emscripten work. It generated a lot of noise in some circles.
Obviously they dissolved/morphed into quite different things.