{"id":3609,"date":"2024-08-19T21:14:25","date_gmt":"2024-08-19T18:14:25","guid":{"rendered":"https:\/\/demensdeum.com\/blog\/2024\/08\/19\/bgfx-emscripten\/"},"modified":"2024-12-16T22:32:13","modified_gmt":"2024-12-16T19:32:13","slug":"bgfx-emscripten","status":"publish","type":"post","link":"https:\/\/demensdeum.com\/blog\/hi\/2024\/08\/19\/bgfx-emscripten\/","title":{"rendered":"Building bgfx Emscripten application"},"content":{"rendered":"<p>In this note I will describe a way to build bgfx applications for the web (WebAssembly) via Emscripten.<\/p>\n<p>The installation platform is Linux x86-64, such as Arch Linux.<\/p>\n<p>First, install Emscripten version 3.1.51, otherwise you won&#8217;t succeed, all because of the change in the type of dynamic libraries in the latest version of Emscripten. You can read more here:<br \/>\n<a href=\"https:\/\/github.com\/bkaradzic\/bgfx\/discussions\/3266\" rel=\"noopener\" target=\"_blank\">https:\/\/github.com\/bkaradzic\/bgfx\/discussions\/3266<\/a <\/p>\n<p>It&#8217;s done like this:<\/p>\n<div class=\"hcb_wrap\">\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-unknown\" data-lang=\"unknown\"><code>\ngit clone https:\/\/github.com\/emscripten-core\/emsdk.git\n\n\n\ncd emsdk\n\n\n\n.\/emsdk install 3.1.51\n\n\n\n.\/emsdk activate 3.1.51\n\n\n\nsource .\/emsdk_env.sh\n\n\n\n<\/code><\/pre>\n<\/div>\n<\/div>\n<p>Let&#8217;s assemble bgfx for WebAssembly &#8211; Emscripten:<\/p>\n<div class=\"hcb_wrap\">\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-unknown\" data-lang=\"unknown\"><code>\nmkdir bgfx-build-test\n\n\n\ncd bgfx-build-test\n\n\n\ngit clone https:\/\/github.com\/bkaradzic\/bx.git\n\n\n\ngit clone https:\/\/github.com\/bkaradzic\/bimg.git\n\n\n\ngit clone https:\/\/github.com\/bkaradzic\/bgfx.git\n\n\n\ncd bgfx\n\n\n\nemmake make wasm-debug\n\n\n\n<\/code><\/pre>\n<\/div>\n<\/div>\n<p>As a result, in the .build folder you will have bitcode files with the .bc extension, which you will need to link with your bgfx application.<br \/>\nThere should be bgfx.bc, bx.bc, bimg.bc; different builds have different names for these files, depending on the build type (release\/debug)<\/p>\n<p>Add a link to .bc files to the CMakeLists.txt file, for example, absolute paths to files from the bgfx-experiments project:<\/p>\n<div class=\"hcb_wrap\">\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-unknown\" data-lang=\"unknown\"><code>\ntarget_link_libraries(${PROJECT_NAME} SDL2 GL \/home\/demensdeum_stream\/Sources\/bgfx-build\/bgfx\/.build\/wasm\/bin\/bgfxDebug.bc \/home\/demensdeum_stream\/Sources\/bgfx-build\/bgfx\/.build\/wasm\/bin\/bxDebug.bc \/home\/demensdeum_stream\/Sources\/bgfx-build\/bgfx\/.build\/wasm\/bin\/bimgDebug.bc)\n\n\n\n<\/code><\/pre>\n<\/div>\n<\/div>\n<p>Now change the native window handle in platform data on bgfx initialization:<\/p>\n<div class=\"hcb_wrap\">\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-unknown\" data-lang=\"unknown\"><code>\nbgfx::PlatformData platformData{};\n\n\n\nplatformData.context = NULL;\n\n\n\nplatformData.backBuffer = NULL;\n\n\n\nplatformData.backBufferDS = NULL;\n\n\n\nplatformData.nwh = (void*)\"#canvas\";\n\n\n\n<\/code><\/pre>\n<\/div>\n<\/div>\n<p>You also need to change the render type to OpenGL:<\/p>\n<div class=\"hcb_wrap\">\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-unknown\" data-lang=\"unknown\"><code>\nbgfx::Init init;\n\n\n\ninit.type = bgfx::RendererType::OpenGL;\n\n\n\n\n\n\n\ninit.resolution.width = screenWidth;\n\n\n\ninit.resolution.height = screenHeight;\n\n\n\ninit.resolution.reset = BGFX_RESET_VSYNC;\n\n\n\ninit.platformData = platformData;\n\n\n\n\n\n\n\nif (!bgfx::init(init))\n\n\n\n{\n\n\n\n    throw std::runtime_error(\"Failed to initialize bgfx\");\n\n\n\n}\n\n\n\n<\/code><\/pre>\n<\/div>\n<\/div>\n<p>Recompile GLSL shaders for 120:<\/p>\n<div class=\"hcb_wrap\">\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-unknown\" data-lang=\"unknown\"><code>\nshaderc -f \"VertexShader.vs\" -o \"VertexShader.glsl\" --type \"v\" -p \"120\"\n\n\n\nshaderc -f \"FragmentShader.fs\" -o \"FragmentShader.glsl\" --type \"f\" -p \"120\"\n\n\n\n<\/code><\/pre>\n<\/div>\n<\/div>\n<p>Of course, .glsl files need to be added to CMakeLists.txt as &#8211;preload-file:<\/p>\n<div class=\"hcb_wrap\">\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-unknown\" data-lang=\"unknown\"><code>\nset(CMAKE_CXX_FLAGS ... <\u041e\u0441\u0442\u0430\u043b\u044c\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u044c>\n\n\n\n--preload-file VertexShader.glsl \\\n\n\n\n--preload-file FragmentShader.glsl \\\n\n\n\n<\/code><\/pre>\n<\/div>\n<\/div>\n<p>All that&#8217;s left is to replace the main render loop in your app with while and call the function via emscripten_set_main_loop.<\/p>\n<p>You can read about it here:<br \/>\n<a href=\"https:\/\/demensdeum.com\/blog\/ru\/2017\/03\/29\/porting-sdl-c-game-to-html5-emscripten\/\" rel=\"noopener\" target=\"_blank\">https :\/\/demensdeum.com\/blog\/ru\/2017\/03\/29\/porting-sdl-c-game-to-html5-emscripten\/<\/a><\/p>\n<p>Then build your Emscripten project as usual, everything should work.<br \/>\nInterestingly &#8211; it seems that the Emscripten 3.1.51 build lacks OpenAL (or maybe it&#8217;s just me).<\/p>\n<p>Source code of the project that builds correctly with bgfx and Emscripten:<br \/>\n<a href=\"https:\/\/github.com\/demensdeum\/bgfx-experiments\/tree\/main\/2-emscripten-build\" rel=\"noopener\" target=\"_blank\">https:\/\/github.com\/demensdeum\/ bgfx-experiments\/tree\/main\/2-emscripten-build<\/a><\/p>\n<p>Sources<\/p>\n<p><a href=\"https:\/\/github.com\/bkaradzic\/bgfx\/discussions\/3266\" rel=\"noopener\" target=\"_blank\">https:\/\/github.com\/bkaradzic\/bgfx\/discussions\/3266 <\/a><br \/>\n<a href=\"https:\/\/bkaradzic.github.io\/bgfx\/build.html\" rel=\"noopener\" target=\"_blank\">https:\/\/bkaradzic.github.io\/bgfx\/build.html<\/a ><br \/>\n<a href=\"https:\/\/emscripten.org\/docs\/getting_started\/downloads.html\" rel=\"noopener\" target=\"_blank\">https:\/\/emscripten.org\/docs\/getting_started\/downloads.html<\/a ><br \/>\n<a href=\"https:\/\/demensdeum.com\/blog\/ru\/2017\/03\/29\/porting-sdl-c-game-to-html5-emscripten\/\" rel=\"noopener\" target=\"_blank\">https :\/\/demensdeum.com\/blog\/ru\/2017\/03\/29\/porting-sdl-c-game-to-html5-emscripten\/<\/a><br \/>\n<a href=\"https:\/\/llvm.org\/docs\/BitCodeFormat.html\" rel=\"noopener\" target=\"_blank\">https:\/\/llvm.org\/docs\/BitCodeFormat.html<\/a><\/p >\n","protected":false},"excerpt":{"rendered":"<p>In this note I will describe a way to build bgfx applications for the web (WebAssembly) via Emscripten. The installation platform is Linux x86-64, such as Arch Linux. First, install Emscripten version 3.1.51, otherwise you won&#8217;t succeed, all because of the change in the type of dynamic libraries in the latest version of Emscripten. You<a class=\"more-link\" href=\"https:\/\/demensdeum.com\/blog\/hi\/2024\/08\/19\/bgfx-emscripten\/\">Continue reading <span class=\"screen-reader-text\">&#8220;Building bgfx Emscripten application&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[6],"tags":[],"class_list":["post-3609","post","type-post","status-publish","format-standard","hentry","category-misc","entry"],"translation":{"provider":"WPGlobus","version":"3.0.2","language":"hi","enabled_languages":["en","ru","zh","de","fr","ja","pt","hi"],"languages":{"en":{"title":true,"content":true,"excerpt":false},"ru":{"title":true,"content":true,"excerpt":false},"zh":{"title":true,"content":true,"excerpt":false},"de":{"title":true,"content":true,"excerpt":false},"fr":{"title":true,"content":true,"excerpt":false},"ja":{"title":true,"content":true,"excerpt":false},"pt":{"title":true,"content":true,"excerpt":false},"hi":{"title":false,"content":false,"excerpt":false}}},"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/demensdeum.com\/blog\/hi\/wp-json\/wp\/v2\/posts\/3609","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/demensdeum.com\/blog\/hi\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/demensdeum.com\/blog\/hi\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/demensdeum.com\/blog\/hi\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/demensdeum.com\/blog\/hi\/wp-json\/wp\/v2\/comments?post=3609"}],"version-history":[{"count":37,"href":"https:\/\/demensdeum.com\/blog\/hi\/wp-json\/wp\/v2\/posts\/3609\/revisions"}],"predecessor-version":[{"id":3859,"href":"https:\/\/demensdeum.com\/blog\/hi\/wp-json\/wp\/v2\/posts\/3609\/revisions\/3859"}],"wp:attachment":[{"href":"https:\/\/demensdeum.com\/blog\/hi\/wp-json\/wp\/v2\/media?parent=3609"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/demensdeum.com\/blog\/hi\/wp-json\/wp\/v2\/categories?post=3609"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/demensdeum.com\/blog\/hi\/wp-json\/wp\/v2\/tags?post=3609"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}