Port of Doom 3 video game (idTech 4 engine) to WebAssembly

1,080 views
Skip to first unread message

Gabriel CV

unread,
Jan 3, 2019, 7:33:41 AM1/3/19
to emscripten-discuss
Hello,

Here is a port of the Doom 3 video game (idTech 4 engine) to WebAssembly using emscripten. This is based the dhewm3 GPL source port, and on the demo data of the game available for download on the web.

Live demo:
=> http://continuation-labs.com/d3wasm

Source code:
=> https://github.com/gabrielcuvillier/dhewm3-webassembly-port

This demonstration is using the demo game data, which is roughly 400MB size. I removed DDS compressed textures and the last level of the demo to shrink things down a little bit. But initial loading will be QUITE long, depending on your bandwidth. Game data files are fetched at initial startup and stored persistently for cache reuse.

Things seems to work correctly on several platforms/browsers I tested. The game is playable on modern browsers. It is even working on mobile Android, though not playable due to lack of controls and really bad performance :)

On my system, the Game runs at 20/40 FPS on Chrome, 10/30 FPS on Firefox (don't know why such slower than Chrome), and 1/2 FPS on my mid-class Android mobile phone ;) Note that the native build shows a constant 60 FPS, but it is not using any GL emulation layer!

A few notes:
- Don't expect to have graphics as shiny as the native build, because the port is not using the "shaders" renderer path (using legacy ARB assembly shaders and not GLSL, this is not supported by WebGL), but instead it uses the fixed function pipeline renderer path that was intended for graphic cards without shader support at the time. It does look nice though, with bumpmapping/reflections & co..

- Some visual glitches though (weird looking specular lights on characters), but they are due to the renderer path used and not because of underlying GL emulation library. The issue is the same with a native build without shader support. However, I had to disable some code in Fog rendering because of issues. As so, Fog is now only partially rendered, and sometime glitchy (you may disable it with "r_skipFogLights 1).

- Loading of levels will "hangs" the display. This is due to the way emscripten works with "main loop based" applications, this model does not support well a loop iteration that last for too long (such as loading a level).

- Under the hood, I use the Regal GL emulation layer library, with quite a few tweaks here and then for things to work.
The fixed function pipeline path used by idTech 4 engine use many of the latest enhancements done to OpenGL before the advent of Shaders (GL 1.4 and co, with Texture combiners, DOT3 bumpmapping, Anisotropy, etc.). As so, Regal is doing a great job to emulate fixed function pipeline.

- Like the previous port I did for Arx Fatalis, I had to disable multithreading from the game code, because it is still difficult to make this work with emscripten.

- I did some tests to enable SIMD/SSE2 code path of the engine, but I discovered it is only supported in asm.js and not in wasm. Too bad!

- I still need to update the README file to explain things a little bit more, including how to build the project (not yet 100% straightforward) and package the data.


Feedback / comments welcomed





Thomas Lively

unread,
Jan 3, 2019, 1:40:27 PM1/3/19
to emscripte...@googlegroups.com
This is super cool! 10/10 will play more when I can. It's really great seeing the WebAssembly work paying off with such a low barrier to start playing such a polished game.

--
You received this message because you are subscribed to the Google Groups "emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to emscripten-disc...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Александр Гурьянов

unread,
Jan 3, 2019, 11:37:21 PM1/3/19
to emscripte...@googlegroups.com
Amazing job! Congrats!

пт, 4 янв. 2019 г., 1:40 'Thomas Lively' via emscripten-discuss emscripte...@googlegroups.com:

Sam Clegg

unread,
Jan 14, 2019, 8:10:44 PM1/14/19
to emscripte...@googlegroups.com
This is awesome!

Our of interest, would it be possible to use Regal to convert the
shader codepath to GLES2/WebGL and avoid the fixed function pipeline?
I assume this would be better for quality and performance?

Also, does emscripten itself have fixed function GL emulation? Why
not just use that over Regal?


On Thu, Jan 3, 2019 at 4:33 AM Gabriel CV <gabriel....@gmail.com> wrote:
>

Gabriel CV

unread,
Jan 29, 2019, 1:24:02 PM1/29/19
to emscripten-discuss
Here it is, I finally completed the rewrite of the backend renderer to WebGL/GLSL + many enhancements. Nice bumpy graphics, and huge performance boost.

Live Demo is here:

Full technical details/article here (TL;DR warning):

And sources on Github.

Enjoy!

Alon Zakai

unread,
Jan 29, 2019, 1:37:49 PM1/29/19
to emscripte...@googlegroups.com
Wow, very impressive! Graphics look perfect now :)

The fullscreen button seems gone? I had to write Module.canvas.requestFullscreen() in the console ;)

--

Gabriel CV

unread,
Jan 30, 2019, 2:21:26 AM1/30/19
to emscripten-discuss
Yes, I've intentionally removed the Fullscreen button, because Doom 3 is a legacy PC game relying on the "Esc" key for a very important thing: to go to the main menu. This is really annoying.
I have to figure out a way to handle this correctly !

Gabriel CV

unread,
Jan 30, 2019, 2:44:02 AM1/30/19
to emscripten-discuss

Obviously feedback is welcomed on the Technical Article, including English speaking/spelling issues (I'm not a native speaker, sorry for that!).

Alon Zakai

unread,
Jan 30, 2019, 8:59:55 AM1/30/19
to emscripte...@googlegroups.com
Oh right, I hit the escape key issue as I was playing...

In my Cube2 port, I ended up mapping the ` key (which is usually right under escape) to escape.

On Tue, Jan 29, 2019 at 11:21 PM Gabriel CV <gabriel....@gmail.com> wrote:
Yes, I've intentionally removed the Fullscreen button, because Doom 3 is a legacy PC game relying on the "Esc" key for a very important thing: to go to the main menu. This is really annoying.
I have to figure out a way to handle this correctly !

Floh

unread,
Jan 31, 2019, 6:20:20 AM1/31/19
to emscripten-discuss
Stretching the WebGL canvas to 100% to cover the whole window client area is a good alternative to "real fullscreen" IMHO. No annoying popups, no reserved keys, and works on all browsers (in real fullscreen there are annoying differences between browsers when using both fullscreen and mouse capture regarding the warning popups).

I do this in my emulators (e.g. https://floooh.github.io/tiny8bit/cpc.html), along with dynamically setting the viewport size to preserve the proper aspect ratio when the browser window is resized.

Gabriel CV

unread,
Jan 31, 2019, 4:46:05 PM1/31/19
to emscripten-discuss
Yes, all those "pointer-locking / fullscreen / popups" issues and behavior differences between browsers are a pain to handle properly.

I guess you are right on the Fullscreen issue, resizing the canvas to 100% is probably a more accurate solution.

Nice work on your emulators btw

Nolan Darilek

unread,
Feb 1, 2019, 10:39:51 AM2/1/19
to emscripte...@googlegroups.com

On one hand, going full-screen blocks use of the escape key. On the other, *not* going full-screen would seem to block the use of far more keys--tab, ctrl-l, etc. Am I mistaken about that?


Is there a way to have the best of both worlds? Take up as much of the screen as possible, permit using most/all keys, but give the user an escape hatch back to the browser? Full-screen and the Escape key seem like the best option for this, but I haven't experimented extensively.

Floh

unread,
Feb 2, 2019, 4:50:02 PM2/2/19
to emscripten-discuss
It's possible to capture most key events and prevent that the browser handles them without going into fullscreen mode. I had the same problem in my emulators with some function keys (for instance F1 would always open the help in Chrome).

This is done by returning "true" from the emscripten key callback functions (I think it doesn't work for things like Ctrl-L though).
To unsubscribe from this group and stop receiving emails from it, send an email to emscripten-discuss+unsub...@googlegroups.com.

Gabriel CV

unread,
Feb 9, 2019, 12:24:53 PM2/9/19
to emscripten-discuss
Finally, I did the following to handle these Fullscreen / Key binding issues:

- ESC key have been replaced by "HOME" key
- Fullscreen button have been re-enabled (this will rescale the canvas, not resize it)
- Actual canvas size / resolution can be changed in-game through the video resolution setting
- Alt-Enter will automatically issue a "vid_restart" command (D3 want you to restart the game after changing resolution, but vid_restart is sufficient)

In practice, this works OK.
Reply all
Reply to author
Forward
0 new messages