Skip to content

Browser platform support#848

Open
ololoken wants to merge 64 commits into
UZDoom:trunkfrom
ololoken:emscripten-trunk
Open

Browser platform support#848
ololoken wants to merge 64 commits into
UZDoom:trunkfrom
ololoken:emscripten-trunk

Conversation

@ololoken

@ololoken ololoken commented Jan 2, 2026

Copy link
Copy Markdown

Description

Adds wasm32 platform support. By default works in 32-bit mode with single thread.
Demo: https://turch.in/uzdoom+ashes2063/index.html?lang=en

Right now it's more PoC for discussion than PR ready to merge.

TODOs:

  • Sync FS callback to persist config changes and saves.
  • rendering, shaders and most annoying bugs.
  • fix save game screenshots
  • Network.
  • Make tools work via nodejs to avoid requirement to build them manually.
  • Add module launcher webpage with options to select WADs and PK3s.
  • Build pipeline

Checklist

@uncreativeCultist

Copy link
Copy Markdown
image probably the first person to run myhouse.wad inside of UZDoom on a web browser. good work, would be cool to see this get merged

@RicardoLuis0

Copy link
Copy Markdown
Contributor

TODOs:
Sync FS callback to persist config changes and saves.
Network.
Make tools work via nodejs to avoid requirement to build them manually.
Add module launcher webpage with options to select WADs and PK3s.

it'd probably also need porting to 64-bit wasm before merging as was mentioned in the forum thread, but really, amazing work on this 🎉

@RicardoLuis0 RicardoLuis0 self-requested a review January 2, 2026 18:03
Comment thread CMakeLists.txt Outdated
Comment on lines +197 to +201
#ifdef __EMSCRIPTEN__
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 0);
#else

@RicardoLuis0 RicardoLuis0 Jan 2, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should probably be done by forcing gles2 on browser, rather than #ifdef-ing the version, that way if GLES3 support is ever added to the opengl3 backend (as a delta touch backport possibly?), webgl2 can be used with full user shader support

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GL context creation is deep in js module guts generated by emscripten. So it's better to set it from "native" code.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GL context creation is deep in js module guts generated by emscripten. So it's better to set it from "native" code.

yeah, but the ifdef'd out code already sets 2.0.0 for GLES in the very same function, that's what i'm confused about

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be honest I just didn't want to search SDL_GL_* attribute which is not supported and ruins context creation, later I will try hunt it.

Comment thread src/d_main.cpp Outdated
Comment thread src/rendering/hwrenderer/scene/hw_bsp.cpp Outdated
Comment thread src/common/rendering/gles/gles_shader.cpp
Comment thread src/CMakeLists.txt

# Non-Windows version also needs SDL except native OS X backend
if( NOT APPLE OR NOT OSX_COCOA_BACKEND )
if( NOT APPLE OR NOT OSX_COCOA_BACKEND AND NOT EMSCRIPTEN )

@RicardoLuis0 RicardoLuis0 Jan 3, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the logic itself might not need it, but it'd be good for parenthesis to be used (since mixing OR and AND)

Comment thread src/common/rendering/r_thread.cpp Outdated
@RicardoLuis0

Copy link
Copy Markdown
Contributor

also this:

https://github.com/UZDoom/UZDoom/blob/trunk/src/common/audio/sound/oalsound.cpp#L639-L643

probably needs an ifdef to check for the emscripten version of openalsoft, or else a bogus warning will be printed

@ololoken

ololoken commented Jan 3, 2026

Copy link
Copy Markdown
Author

also this:

https://github.com/UZDoom/UZDoom/blob/trunk/src/common/audio/sound/oalsound.cpp#L639-L643

probably needs an ifdef to check for the emscripten version of openalsoft, or else a bogus warning will be printed

It's better to check if AL_VENDOR == "Emscripten"

@RicardoLuis0

Copy link
Copy Markdown
Contributor

also this:
https://github.com/UZDoom/UZDoom/blob/trunk/src/common/audio/sound/oalsound.cpp#L639-L643
probably needs an ifdef to check for the emscripten version of openalsoft, or else a bogus warning will be printed

It's better to check if AL_VENDOR == "Emscripten"

image

yeah, just something so that this warning doesn't print

@kcat

kcat commented Jan 3, 2026

Copy link
Copy Markdown
Contributor

yeah, just something so that this warning doesn't print

Certain things won't work without OpenAL Soft features, like sounds that use loop points (which don't cover the whole sound) or use stereo sound for 3D/world sounds, and "area sounds" may not sound correct. Some warning that the audio may sound wrong may be appropriate.

@RicardoLuis0

Copy link
Copy Markdown
Contributor

yeah, just something so that this warning doesn't print

Certain things won't work without OpenAL Soft features, like sounds that use loop points (which don't cover the whole sound) or use stereo sound for 3D/world sounds, and "area sounds" may not sound correct. Some warning that the audio may sound wrong may be appropriate.

afaik emscripten supports a ton of openal features

@RicardoLuis0

Copy link
Copy Markdown
Contributor

yep, loop points, spatial sounds, hrtf, etc
image
https://emscripten.org/docs/porting/Audio.html

@github-actions

github-actions Bot commented Jan 3, 2026

Copy link
Copy Markdown

Thanks for opening this PR! We'll review it soon.

I'm a bot that checks for some common problems. I'll update this comment with anything I find.

Looks like it's your first time contributing!

  • Welcome the community and thank you for your contribution! Please take a moment to familiarize yourself with the resources available in our README.md file.
  • Please take a moment to add your name to the bottom of the CONTRIBUTORS file!

Here are some minor issues, that might need fixing:

  • Head's up, libraries/ZMusic/ is a subtree. Please ensure you're pushing these changes upstream.
  • Head's up, libraries/ZWidget/ is a subtree. Please ensure you're pushing these changes upstream.

@Lunascaped

Copy link
Copy Markdown

not sure if its just me but i get a lot of weird mouse snapping with this, would be cool if it was fixed before merging.

2026-01-03.23-09-44.9MB.mp4

@babycommando

Copy link
Copy Markdown

Absolutely unbelievable. It works so damn well!!! Congratulations, this is absolutely legendary.

Just tested and its working like a charm. What is preventing this to be merged officially? Are you working on in something specific at the moment?

About networking, do you have a plan to approach it?

Thanks!!

@RicardoLuis0

Copy link
Copy Markdown
Contributor

What is preventing this to be merged officially?

  1. 5.0 is mostly under feature freeze for unplanned stuff
  2. commit history is incredibly messy, so it is unmergeable and unreviewable as-is, would need cleaning up before it can be reviewed, and it obviously needs to be reviewed before it can be merged

@babycommando

Copy link
Copy Markdown

Thanks @RicardoLuis0 for the kind response. Perhaps I can try helping making sense of stuff.

Honestly this is the only gzdoom/uzdoom wasm implementation working on the internet at the moment, and it works very well. Legendary works. Will be amazing to make all that ztuff run in the browser, open many possibilities for the future of videogames lol

@ololoken what are you working on at the moment?

@ololoken

Copy link
Copy Markdown
Author

@babycommando I'm working on Serios Sam.
Network implementation for browser requires infrastructure like running signalling server. We can emulate local network in browser using webrtc datachannels. You can find example how it's done here:
https://github.com/ololoken/xash3d-fwgs/tree/master/engine/platform/emscripten and https://github.com/ololoken/xash3d-launcher/blob/main/src/assets/module/vnet.ts

@RicardoLuis0 totally agree

I will continue wasm fork support.

Another demo:
https://turch.in/voxeldoom/index.html

@babycommando

babycommando commented May 27, 2026

Copy link
Copy Markdown

Hey @ololoken, woah Voxel Doom <3

I just cloned your branch at https://github.com/ololoken/UZDoom/tree/emscripten-trunk and tried building locally, but got stuck around libvpx and Zmusic / fluidsynth.

Currently trying to wrap my brain around how you made a couple things there.

  • have you built libvpx manually separately with emscripten, or used some prebuilt lib?
  • how do you handle Zmusic fluidsynth and the audio deps stuff?
  • do you first build native tools like lemon, re2c, zipdir, then run the wasm build?

Could you share how you usually build it? Perhaps you have the exact emcmake cmake commands or a rough script, if you could share the sequence it would be helpful.

The demos work beautifully, so I'm clearly missing something in the build setup.

Thanks again, this fork is seriously amazing!!

@ololoken

ololoken commented May 27, 2026

Copy link
Copy Markdown
Author

@babycommando it's supposed that you have to build 3rd party libraries using emscripten toolchain. Just emmake make install and in common case dependency will be automatically resolved
And yes for now build lemon, re2c and zipdir as native. I know there are ways to configure crosscompilation for such cases, but first want to try build them as node wasm modules .

@babycommando

babycommando commented May 27, 2026

Copy link
Copy Markdown

@ololoken Got it, that makes sense now.
I did a clean emcmake configure. Native lemon/re2c/zipdir are already built and copied, and that part seems fine. But still haven't figured out libvpx and glib-2.0 required by Zmusic and fluidsynth.

So for your local build, do you just build/install libvpx and glib with emconfigure/emmake into the Emscripten environment, then rerun UZDoom cmake? Or do you avoid glib by patching bundled fluidsynth to use the glib stubs for EMSCRIPTEN? Also, for VPX, are you using upstream libvpx with emconfigure ./configure && emmake make install?

update: managed to compile libvpx locally so the project dont cry more about it, but glib-2.0 used by ZMusic still a problem, when trying to build it I'm getting:
subprojects/libffi/meson.build: Unsupported pair: system "emscripten", cpu family "wasm32"
Wonder how you got past that at all if you even built glib-2.0 in first place. Looks like libffi have an Emscripten port at hoodmane/libffi-emscripten repo. Have you used that? Yep, lets build the dependence of a dependence to see if it works cause why not, right haha. If UZDoom uses it can be helpful anyways I guess.

update 2: finally got to build glib-2.0 manually, I ended up indeed replacing libffi with that emscripten version and it worked. Also later on when compiling it, it also asked about building zlib manually. After that, I finally got glib-2.0 far enough to stop failing at configure.
Now UZDoom is actually compiling much deeper, but Im hitting a wave of C and Cpp portability issues: missing includes like cstring, algorithm, cstdint, C headers accidentally getting C++ includes, etc. So got some progress, but honestly its still pretty cursed. You said to just emmake make install, so I am probably doing something wrong. Spent the day trying to compile this lol.

update 3: got past the huge C/Cpp error wave! The mistake was building it with vulkan not disabled. Now I'm passing the flag -DHAVE_VULKAN=OFF and it seems to be building.

update 4: Phew, after a long time it finally compiled, I put it over some dumb html file to see what happens, initially it was only throwing a cpp pointer errors 🤣 but it was just me not mounting the wad correctly.

It worked!!! Music, performance, everything working just so well.
Captura de tela 2026-05-28 034156
freedoom2 voxelized man!

It is lovely to finally see this running. Also could you provide the html and js files you are hosting the wasm into?

Perhaps it would be way more helpful if you could just share an installation instruction of what to do from the moment I clone the repo to build and run it so we don't fall on those traps anymore. Also did everything on windows powershell which might have been an extra problem. Anyway this is legendary ::) Thanks!

@babycommando

babycommando commented May 29, 2026

Copy link
Copy Markdown

@ololoken let me know if you read my previous message up there. If you could provide installation instructions that you are doing in your environment, as well as the html/js if possible for the demo page it would be very, very nice. Thanks. It was super cool to make it run but I lost some time on it building random stuff as mentioned previously, probably did something wrong.

Also nice that you got lemon, re2c and zipdir as the node wasm modules now.
But libvpx and the FluidSynth -> glib-2.0 -> libffi/zlib chain still look like separate prerequisites, unless there is another setup script I missed?

thanks!

@babycommando babycommando left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is indeed solving the problem of having to do the hackish workaround for lemon, re2c and zipdir. Gracefully fixes that part, thanks. Perhaps we can make libvpx and FluidSynth (glib-2.0 -> libffi/zlib) build automatically as well as part of the next commits

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants