Wasm fractal

Intro

Since 2000's I have had some tech-dream to use one language to write and its results are available to all people independent of platform. In 2020 when WebAssembly is available by default on all platforms and all major languages are able to translate source code to WebAssembly this era is here ;]. There was time when java applets nad adobe flash where main technologies for interactive web demos, now everything could be done with javascript, but also old-style languages like C are able to run latest tech in browser woohoo.

Insights

As demo works on linux and in browser there is some quirks to overcome to make code compatible for both technologies. It wasnt straight away to just compile and join app SDL+OpenGL for wasm.

Main loop

Each C program have main entry point. And SDL programm usual structure include loop that get events and execute them.

//Usual SDL code
SDL_Event event;
    SDL_StartTextInput();
        while (SDL_PollEvent(&event) != 0)
        {
            switch (event.type)
                {
                    case SDL_QUIT:
                    {
                        quit = 1;
                        break;
                    }
                    case SDL_KEYDOWN:
                    {
                        switch (event.key.keysym.sym)
                        {
                        case SDLK_DOWN:
                        }
                    }
                }
        }

As wasm is running in browser as canvas, then graphics context rendering is controlled from ui thread so this loop cannot run all the time, and need to return back to ui thread.

void main_loop()
{

#if __EMSCRIPTEN__
    emscripten_set_main_loop(main_tick, 25, 1);
#else
    while (0 == quit)
    {
        main_tick();
    }
#endif
}

Main loop where moved to single function. And now its able to run in single cycle for wasm, and behave as loop for other platforms.

Static queue

Allocating space in wasm from C with malloc is not supported. There is possibility to write wrapper that manages static allocated memory, and create wrapper to alloc/dealloc memory. Or there is possible to create arrays from js and pass buffer to wasm binary. Easier is just to allocate static buffer. Queue that saves data for fractal iterations is saved in static allocated buffer.

Color pallets

Shaders

First versions of drawing loop didn't worked out of the box in browse. There was spent some time to find a way to run shader. Got errors in shader language in browser, while on linux evertyhing was working. There is version difference between shader language supported between linux and was platform. Main fix was to define earlier shader language version.

    "#version 100 \n"
    "attribute vec4 position;    \n"
    "attribute vec4 colour;      \n"
    "varying vec4 interpolated_colour;\n"
    "void main()                  \n"
    "{                            \n"
    "   interpolated_colour = colour;\n"
    "   gl_Position = position;  \n"
    "   \n"
    "}

SDL+GL and compilation

On linux OpenGLES library where used while it have less features then full OpenGL, for current purpose is have everything. To enable different versions of GL on wasm need to search for available options inside emscripten sdk js-configuration file.

Compile on linux

-lSDL2 -lSDL2_ttf -lGLESv2 -lGL

Compile with emscripten

-s USE_SDL=2 -s MAX_WEBGL_VERSION=2 -s MIN_WEBGL_VERSION=2 -s LLD_REPORT_UNDEFINED -s USE_GLFW=3

Demo page

Permanent residence of demo, with latest version available
Demo - http://wasm.main.lv/fractal

Thx

developers.lv - for first tryouts daGrevis,Aleksejs,Tenjou

Source

Source provided as is, no any attempt to make it easy to build is made. http://git.main.lv/cgit.cgi/wasm_fractal.git/

Links

[01] main.lv/writeup/web_assembly_sdl_example.md
[02] https://github.com/opengl-tutorials/ogl/blob/master/tutorial04_colored_cube/tutorial04.cpp
[03] https://arm-software.github.io/opengl-es-sdk-for-android/introduction_to_shaders.html
[04] https://gist.github.com/SuperV1234/5c5ad838fe5fe1bf54f9