Emscripten build

This commit is contained in:
kevinbchen 2021-01-04 00:58:24 -08:00
parent 63466dc2ea
commit 6ade1624f1
4 changed files with 115 additions and 79 deletions

View File

@ -89,13 +89,16 @@ endif()
# Link and create SDL2 Definition if we're using it # Link and create SDL2 Definition if we're using it
if (SDL2_ENABLED) if (SDL2_ENABLED)
add_compile_definitions(BLAH_USE_SDL2) add_compile_definitions(BLAH_USE_SDL2)
if (${CMAKE_SYSTEM_NAME} MATCHES "Emscripten")
if (NOT DEFINED SDL2_INCLUDE_DIRS OR NOT DEFINED SDL2_LIBRARIES) set_target_properties(blah PROPERTIES COMPILE_FLAGS "-s USE_SDL=2")
find_package(SDL2 REQUIRED) else()
if (NOT DEFINED SDL2_INCLUDE_DIRS OR NOT DEFINED SDL2_LIBRARIES)
find_package(SDL2 REQUIRED)
endif()
target_include_directories(blah PUBLIC "$<BUILD_INTERFACE:${SDL2_INCLUDE_DIRS}>")
set(LIBS ${LIBS} ${SDL2_LIBRARIES})
endif() endif()
target_include_directories(blah PUBLIC "$<BUILD_INTERFACE:${SDL2_INCLUDE_DIRS}>")
set(LIBS ${LIBS} ${SDL2_LIBRARIES})
endif() endif()
target_link_libraries(blah PUBLIC ${LIBS}) target_link_libraries(blah PUBLIC ${LIBS})

View File

@ -7,13 +7,20 @@
#include "../internal/graphics_backend.h" #include "../internal/graphics_backend.h"
#include "../internal/input_backend.h" #include "../internal/input_backend.h"
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#include <emscripten/html5.h>
#endif
using namespace Blah; using namespace Blah;
namespace namespace
{ {
Config app_config; static Config app_config;
bool app_is_running = false; static bool app_is_running = false;
bool app_is_exiting = false; static bool app_is_exiting = false;
static uint64_t time_last;
static uint64_t time_accumulator = 0;
} }
Config::Config() Config::Config()
@ -34,6 +41,79 @@ Config::Config()
on_error = nullptr; on_error = nullptr;
} }
namespace {
void loop_iteration() {
// poll system events
PlatformBackend::frame();
// update at a fixed timerate
// TODO: allow a non-fixed step update?
{
uint64_t time_target = (uint64_t)((1.0f / app_config.target_framerate) * 1000);
uint64_t time_curr = PlatformBackend::time();
uint64_t time_diff = time_curr - time_last;
time_last = time_curr;
time_accumulator += time_diff;
// do not let us run too fast
while (time_accumulator < time_target)
{
PlatformBackend::sleep((int)(time_target - time_accumulator));
time_curr = PlatformBackend::time();
time_diff = time_curr - time_last;
time_last = time_curr;
time_accumulator += time_diff;
}
// Do not allow us to fall behind too many updates
// (otherwise we'll get spiral of death)
uint64_t time_maximum = app_config.max_updates * time_target;
if (time_accumulator > time_maximum)
time_accumulator = time_maximum;
// do as many updates as we can
while (time_accumulator >= time_target)
{
time_accumulator -= time_target;
Time::delta = (1.0f / app_config.target_framerate);
if (Time::pause_timer > 0)
{
Time::pause_timer -= Time::delta;
if (Time::pause_timer <= -0.0001f)
Time::delta = -Time::pause_timer;
else
continue;
}
Time::milliseconds += time_target;
Time::previous_elapsed = Time::elapsed;
Time::elapsed += Time::delta;
InputBackend::frame();
GraphicsBackend::frame();
if (app_config.on_update != nullptr)
app_config.on_update();
}
}
// render
{
GraphicsBackend::before_render();
if (app_config.on_render != nullptr)
app_config.on_render();
GraphicsBackend::after_render();
PlatformBackend::present();
}
}
} // namespace
bool App::run(const Config* c) bool App::run(const Config* c)
{ {
BLAH_ASSERT(!app_is_running, "The Application is already running"); BLAH_ASSERT(!app_is_running, "The Application is already running");
@ -68,83 +148,20 @@ bool App::run(const Config* c)
if (app_config.on_startup != nullptr) if (app_config.on_startup != nullptr)
app_config.on_startup(); app_config.on_startup();
uint64_t time_last = PlatformBackend::time(); time_last = PlatformBackend::time();
uint64_t time_accumulator = 0; time_accumulator = 0;
// display window // display window
PlatformBackend::ready(); PlatformBackend::ready();
#ifdef __EMSCRIPTEN__
emscripten_set_main_loop(loop_iteration, 0, 1);
#else
while (!app_is_exiting) while (!app_is_exiting)
{ {
// poll system events loop_iteration();
PlatformBackend::frame();
// update at a fixed timerate
// TODO: allow a non-fixed step update?
{
uint64_t time_target = (uint64_t)((1.0f / app_config.target_framerate) * 1000);
uint64_t time_curr = PlatformBackend::time();
uint64_t time_diff = time_curr - time_last;
time_last = time_curr;
time_accumulator += time_diff;
// do not let us run too fast
while (time_accumulator < time_target)
{
PlatformBackend::sleep((int)(time_target - time_accumulator));
time_curr = PlatformBackend::time();
time_diff = time_curr - time_last;
time_last = time_curr;
time_accumulator += time_diff;
}
// Do not allow us to fall behind too many updates
// (otherwise we'll get spiral of death)
uint64_t time_maximum = app_config.max_updates * time_target;
if (time_accumulator > time_maximum)
time_accumulator = time_maximum;
// do as many updates as we can
while (time_accumulator >= time_target)
{
time_accumulator -= time_target;
Time::delta = (1.0f / app_config.target_framerate);
if (Time::pause_timer > 0)
{
Time::pause_timer -= Time::delta;
if (Time::pause_timer <= -0.0001f)
Time::delta = -Time::pause_timer;
else
continue;
}
Time::milliseconds += time_target;
Time::previous_elapsed = Time::elapsed;
Time::elapsed += Time::delta;
InputBackend::frame();
GraphicsBackend::frame();
if (app_config.on_update != nullptr)
app_config.on_update();
}
}
// render
{
GraphicsBackend::before_render();
if (app_config.on_render != nullptr)
app_config.on_render();
GraphicsBackend::after_render();
PlatformBackend::present();
}
} }
#endif
// shutdown // shutdown
if (app_config.on_shutdown != nullptr) if (app_config.on_shutdown != nullptr)

View File

@ -19,7 +19,11 @@ namespace
const ShaderData shader_data = { const ShaderData shader_data = {
// vertex shader // vertex shader
#ifdef __EMSCRIPTEN__
"#version 300 es\n"
#else
"#version 330\n" "#version 330\n"
#endif
"uniform mat4 u_matrix;\n" "uniform mat4 u_matrix;\n"
"layout(location=0) in vec2 a_position;\n" "layout(location=0) in vec2 a_position;\n"
"layout(location=1) in vec2 a_tex;\n" "layout(location=1) in vec2 a_tex;\n"
@ -37,7 +41,12 @@ namespace
"}", "}",
// fragment shader // fragment shader
#ifdef __EMSCRIPTEN__
"#version 300 es\n"
"precision mediump float;\n"
#else
"#version 330\n" "#version 330\n"
#endif
"uniform sampler2D u_texture;\n" "uniform sampler2D u_texture;\n"
"in vec2 v_tex;\n" "in vec2 v_tex;\n"
"in vec4 v_col;\n" "in vec4 v_col;\n"

View File

@ -81,6 +81,10 @@ bool PlatformBackend::init(const Config* config)
{ {
flags |= SDL_WINDOW_OPENGL; flags |= SDL_WINDOW_OPENGL;
#ifdef __EMSCRIPTEN__
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
#else
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
@ -93,6 +97,7 @@ bool PlatformBackend::init(const Config* config)
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4); SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4);
#endif
} }
// enable DirectX // enable DirectX
else if (App::renderer() == Renderer::D3D11) else if (App::renderer() == Renderer::D3D11)
@ -140,9 +145,11 @@ bool PlatformBackend::init(const Config* config)
void PlatformBackend::ready() void PlatformBackend::ready()
{ {
#ifndef __EMSCRIPTEN__
// enable V-Sync // enable V-Sync
if (App::renderer() == Renderer::OpenGL) if (App::renderer() == Renderer::OpenGL)
SDL_GL_SetSwapInterval(1); SDL_GL_SetSwapInterval(1);
#endif
} }
void PlatformBackend::shutdown() void PlatformBackend::shutdown()