pongasoft / emscripten-glfw

This project is an emscripten port of GLFW written in C++ for the web/webassembly platform #wasm
https://pongasoft.github.io/emscripten-glfw/test/demo/main.html
Apache License 2.0
78 stars 3 forks source link
cpp emscripten glfw3 wasm webassembly

Introduction

This project is an Emscripten port of GLFW written in C++ for the web/wasm platform. The currently supported GLFW API is 3.4.

emscripten - 3.1.69 Latest - 3.4.0.20241004 GLFW - 3.4.0 License Compiles

Goal

The main goal of this project is to implement as much of the GLFW API that is possible to implement in the context of a web browser.

Since this project is targeting the web/webassembly platform, which runs in more recent web browsers, it is also trying to focus on using the most recent features and not use deprecated features (for example, uses keyboardEvent.key vs keyboardEvent.charcode). As a result, this implementation will most likely not work in older browsers.

Since the code is written in C++, it is trying to minimize the amount of JavaScript code to remain clean and lean.

Features

Main features:

[!NOTE] The Comparison page details the differences between this implementation and the Emscripten built-in one.

Demo

emscripten_glfw

Check out the live demo of the example code. Note that you need to use a "modern" browser to see it in action. Currently tested on Google Chrome 120+ and Firefox 121+.

The code for the demo is included in this project.

The demo shows 2 canvases each created via a glfwCreateWindow and shows how they respond to keyboard and mouse events (using direct apis, like glfwGetMouseButton or callback apis like glfwSetMouseButtonCallback)

You can enable/disable each window/canvas independently:

The demo uses webgl to render a triangle (the hellow world of gpu rendering...).

Live Applications

ApplicationDescription
WebGPU Shader Toy (src) WebGPU Shader Toy is a free and open source tool for experimenting with WebGPU fragment shaders and the WebGPU Shader Language (WGSL)

Examples (part of this project)

ExampleNote
Demo (src)Main test/demo which demonstrates most features of the implementation
example_asyncify (src) The purpose of this example is to demonstrate how to use asyncify which allows the code to be written like you would for a normal desktop application
example_hi_dpi (src) The purpose of this example is to demonstrate how to make the window Hi DPI aware
example_minimal (src) The purpose of this example is to be as minimal as possible: initializes glfw, creates a window, then destroys it and terminates glfw. Uses the default shell that comes with emscripten
example_resizable_container (src) The purpose of this example is to demonstrate how to make the canvas resizable with another container (a surrounding div) driving its size. The container width is proportional to the size of the window and so as the window gets resized so does the div, and so does the canvas
example_resizable_container_with_handle (src) The purpose of this example is to demonstrate how to make the canvas resizable with a container that has a handle. The handle can be dragged around (left mouse drag), and the div is resized accordingly which in turn resizes the canvas, making the canvas truly resizable like a window
example_resizable_full_window (src) The purpose of this example is to demonstrate how to make the canvas resizable and occupy the full window

Integration

Since ImGui v1.91.0, ImGui can be configured to use this port, allowing full gamepad and clipboard support amongst many other advantages.

Quick start (Emscripten port)

Since Emscripten 3.1.55, using this library is really easy via the Emscripten use-port option: --use-port=contrib.glfw3 (no need to clone this repo at all!). This is the recommended method to use this project.

Command line

Example:

emcc --use-port=contrib.glfw3 main.cpp -o build/index.html

CMake

With CMake, you need to provide the option both for compile and link phases:

target_compile_options(${target} PUBLIC "--use-port=contrib.glfw3")
target_link_options(${target} PUBLIC "--use-port=contrib.glfw3")

Makefile

This is an example from ImGui (examples/example_emscripten_wgpu)

EMS += -s DISABLE_EXCEPTION_CATCHING=1 --use-port=contrib.glfw3
#LDFLAGS += -s USE_GLFW=3 -s USE_WEBGPU=1
LDFLAGS += -s USE_WEBGPU=1

Port Options

The port can be configured with the following options:

Option Description
disableJoystick Boolean to disable support for joystick entirely, which can be useful if you don't need it due to polling
disableWarning Boolean to disable warnings emitted by the library (for example when using non supported features)
disableMultiWindow Boolean to disable multi window support which makes the code smaller and faster if you don't need it

Example using disableWarning and disableMultiWindow:

emcc --use-port=contrib.glfw3:disableWarning=true:disableMultiWindow=true main.cpp -o build

Note about availability in Emscripten

Emscripten this port
3.1.69 3.4.0.20241004
3.1.66 3.4.0.20240907
3.1.65 3.4.0.20240817
3.1.63 3.4.0.20240627
3.1.60 3.4.0.20240514
3.1.57 3.4.0.20240318
3.1.56 1.1.0
3.1.55 1.0.5

Due to the release cadence of Emscripten, if you want to be in charge of which version you use, you can simply use the port that is checked-in under port: --use-port=port/emscripten-glfw3.py

[!NOTE] Emscripten automatically downloads and builds the library for you and stores it in its cache. If you want to delete the library from the cache, you can use the embuilder tool:

# remove library from cache
embuilder clear contrib.glfw3
# remove library from cache (with options)
embuilder clear contrib.glfw3:disableWarning=true:disableMultiWindow=true

Documentation

Check the documentation for details on how to use this implementation, including clipboard, joystick, resizable canvas, Hi DPI, etc... Note that care has been taken to be backward compatible with the pure JavaScript Emscripten built-in implementation.

Release Notes

3.4.0.20241004 - 2024-10-04 | Emscripten 3.1.69

3.4.0.20240907 - 2024-09-07 | Emscripten 3.1.66

3.4.0.20240817 - 2024-08-17 | Emscripten 3.1.65

[!WARNING] Breaking changes! The clipboard async API has been removed. Note that due to emscripten release cadence, these changes were never part of the emscripten port, so it is unlikely going to affect your project. Check the Clipboard support section for details on how to deal with the clipboard in your application.

3.4.0.20240804 - 2024-08-04 | Emscripten 3.1.65

3.4.0.20240731 - 2024-07-31 | Emscripten 3.1.65

3.4.0.20240727 - 2024-07-27 | Emscripten 3.1.65

3.4.0.20240627 - 2024-06-27 | Emscripten 3.1.63

3.4.0.20240625 - 2024-06-25 | Emscripten 3.1.63

3.4.0.20240617 - 2024-06-17 | Emscripten 3.1.63

3.4.0.20240616 - 2024-06-16 | Emscripten 3.1.63

3.4.0.20240601 - 2024-06-01 | Emscripten 3.1.63

3.4.0.20240514 - 2024-05-14 | Emscripten 3.1.60

3.4.0.20240501 - 2024-05-01 | Emscripten 3.1.60

3.4.0.20240318 - 2024-03-18 | Emscripten 3.1.57

1.1.0 - 2024-02-29 | Emscripten 3.1.56

1.0.5 - 2024/02/18 | Emscripten 3.1.55

1.0.4 - 2024/01/24

1.0.3 - 2024/01/23

1.0.2 - 2024/01/22

1.0.1 - 2024/01/21

1.0.0 - 2024/01/21

wip-0.5.0 - 2024/01/12

wip-0.4.0 - 2024/01/03

wip-0.3.0 - 2023/12/31

wip-0.2.0 - 2023/12/28

wip-0.1.0 - 2023/12/26

Misc

This project includes the glfw3.h header (external/GLFW/glfw3.h) which uses a ZLib license

Licensing