diff options
author | Matthew Kosarek <mattkae@protonmail.com> | 2021-03-27 11:49:56 -0400 |
---|---|---|
committer | Matthew Kosarek <mattkae@protonmail.com> | 2021-03-27 11:49:56 -0400 |
commit | 58488f8eabcc61089e0ae4297f38f10cc28d78c7 (patch) | |
tree | 81ac504e61c57c7228024ad40710f782a3d8c884 | |
parent | 26ea81c5893778a7fa4ecbb2e8f561c9edabd0b3 (diff) |
Working reusable simulation loop
-rw-r--r-- | frontend/2d/_collisions/pill_line/dist/output.js | 112 | ||||
-rwxr-xr-x | frontend/2d/_collisions/pill_line/dist/output.wasm | bin | 26316 -> 27360 bytes | |||
-rw-r--r-- | frontend/2d/_collisions/pill_line/main.cpp | 53 | ||||
-rw-r--r-- | frontend/roadmap.html | 2 | ||||
-rw-r--r-- | frontend/shared_cpp/MainLoop.cpp | 30 | ||||
-rw-r--r-- | frontend/shared_cpp/MainLoop.h | 29 | ||||
-rw-r--r-- | frontend/shared_cpp/OrthographicRenderer.cpp | 2 | ||||
-rw-r--r-- | frontend/shared_cpp/WebglContext.h | 10 |
8 files changed, 164 insertions, 74 deletions
diff --git a/frontend/2d/_collisions/pill_line/dist/output.js b/frontend/2d/_collisions/pill_line/dist/output.js index 0a96183..e1dfee3 100644 --- a/frontend/2d/_collisions/pill_line/dist/output.js +++ b/frontend/2d/_collisions/pill_line/dist/output.js @@ -252,7 +252,9 @@ moduleOverrides = null; // to the proper local x. This has two benefits: first, we only emit it if it is // expected to arrive, and second, by using a local everywhere else that can be // minified. -if (Module['arguments']) arguments_ = Module['arguments'];if (!Object.getOwnPropertyDescriptor(Module, 'arguments')) { + +if (Module['arguments']) arguments_ = Module['arguments']; +if (!Object.getOwnPropertyDescriptor(Module, 'arguments')) { Object.defineProperty(Module, 'arguments', { configurable: true, get: function() { @@ -260,7 +262,9 @@ if (Module['arguments']) arguments_ = Module['arguments'];if (!Object.getOwnProp } }); } -if (Module['thisProgram']) thisProgram = Module['thisProgram'];if (!Object.getOwnPropertyDescriptor(Module, 'thisProgram')) { + +if (Module['thisProgram']) thisProgram = Module['thisProgram']; +if (!Object.getOwnPropertyDescriptor(Module, 'thisProgram')) { Object.defineProperty(Module, 'thisProgram', { configurable: true, get: function() { @@ -268,7 +272,9 @@ if (Module['thisProgram']) thisProgram = Module['thisProgram'];if (!Object.getOw } }); } -if (Module['quit']) quit_ = Module['quit'];if (!Object.getOwnPropertyDescriptor(Module, 'quit')) { + +if (Module['quit']) quit_ = Module['quit']; +if (!Object.getOwnPropertyDescriptor(Module, 'quit')) { Object.defineProperty(Module, 'quit', { configurable: true, get: function() { @@ -288,6 +294,7 @@ assert(typeof Module['readAsync'] === 'undefined', 'Module.readAsync option was assert(typeof Module['readBinary'] === 'undefined', 'Module.readBinary option was removed (modify readBinary in JS)'); assert(typeof Module['setWindowTitle'] === 'undefined', 'Module.setWindowTitle option was removed (modify setWindowTitle in JS)'); assert(typeof Module['TOTAL_MEMORY'] === 'undefined', 'Module.TOTAL_MEMORY has been renamed Module.INITIAL_MEMORY'); + if (!Object.getOwnPropertyDescriptor(Module, 'read')) { Object.defineProperty(Module, 'read', { configurable: true, @@ -296,6 +303,7 @@ if (!Object.getOwnPropertyDescriptor(Module, 'read')) { } }); } + if (!Object.getOwnPropertyDescriptor(Module, 'readAsync')) { Object.defineProperty(Module, 'readAsync', { configurable: true, @@ -304,6 +312,7 @@ if (!Object.getOwnPropertyDescriptor(Module, 'readAsync')) { } }); } + if (!Object.getOwnPropertyDescriptor(Module, 'readBinary')) { Object.defineProperty(Module, 'readBinary', { configurable: true, @@ -312,6 +321,7 @@ if (!Object.getOwnPropertyDescriptor(Module, 'readBinary')) { } }); } + if (!Object.getOwnPropertyDescriptor(Module, 'setWindowTitle')) { Object.defineProperty(Module, 'setWindowTitle', { configurable: true, @@ -562,7 +572,9 @@ function getCompilerSetting(name) { // An online HTML version (which may be of a different version of Emscripten) // is up at http://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html -var wasmBinary;if (Module['wasmBinary']) wasmBinary = Module['wasmBinary'];if (!Object.getOwnPropertyDescriptor(Module, 'wasmBinary')) { +var wasmBinary; +if (Module['wasmBinary']) wasmBinary = Module['wasmBinary']; +if (!Object.getOwnPropertyDescriptor(Module, 'wasmBinary')) { Object.defineProperty(Module, 'wasmBinary', { configurable: true, get: function() { @@ -570,7 +582,8 @@ var wasmBinary;if (Module['wasmBinary']) wasmBinary = Module['wasmBinary'];if (! } }); } -var noExitRuntime;if (Module['noExitRuntime']) noExitRuntime = Module['noExitRuntime'];if (!Object.getOwnPropertyDescriptor(Module, 'noExitRuntime')) { +var noExitRuntime = Module['noExitRuntime'] || true; +if (!Object.getOwnPropertyDescriptor(Module, 'noExitRuntime')) { Object.defineProperty(Module, 'noExitRuntime', { configurable: true, get: function() { @@ -1182,7 +1195,8 @@ function updateGlobalBufferAndViews(buf) { var TOTAL_STACK = 5242880; if (Module['TOTAL_STACK']) assert(TOTAL_STACK === Module['TOTAL_STACK'], 'the stack size can no longer be determined at runtime') -var INITIAL_MEMORY = Module['INITIAL_MEMORY'] || 16777216;if (!Object.getOwnPropertyDescriptor(Module, 'INITIAL_MEMORY')) { +var INITIAL_MEMORY = Module['INITIAL_MEMORY'] || 16777216; +if (!Object.getOwnPropertyDescriptor(Module, 'INITIAL_MEMORY')) { Object.defineProperty(Module, 'INITIAL_MEMORY', { configurable: true, get: function() { @@ -1760,6 +1774,15 @@ var ASM_CONSTS = { HEAPU8.copyWithin(dest, src, src + num); } + function _emscripten_request_animation_frame_loop(cb, userData) { + function tick(timeStamp) { + if (wasmTable.get(cb)(timeStamp, userData)) { + requestAnimationFrame(tick); + } + } + return requestAnimationFrame(tick); + } + function _emscripten_get_heap_size() { return HEAPU8.length; } @@ -1777,32 +1800,31 @@ var ASM_CONSTS = { // anyhow) } function _emscripten_resize_heap(requestedSize) { - requestedSize = requestedSize >>> 0; var oldSize = _emscripten_get_heap_size(); // With pthreads, races can happen (another thread might increase the size in between), so return a failure, and let the caller retry. assert(requestedSize > oldSize); // Memory resize rules: - // 1. When resizing, always produce a resized heap that is at least 16MB (to avoid tiny heap sizes receiving lots of repeated resizes at startup) - // 2. Always increase heap size to at least the requested size, rounded up to next page multiple. - // 3a. If MEMORY_GROWTH_LINEAR_STEP == -1, excessively resize the heap geometrically: increase the heap size according to + // 1. Always increase heap size to at least the requested size, rounded up to next page multiple. + // 2a. If MEMORY_GROWTH_LINEAR_STEP == -1, excessively resize the heap geometrically: increase the heap size according to // MEMORY_GROWTH_GEOMETRIC_STEP factor (default +20%), // At most overreserve by MEMORY_GROWTH_GEOMETRIC_CAP bytes (default 96MB). - // 3b. If MEMORY_GROWTH_LINEAR_STEP != -1, excessively resize the heap linearly: increase the heap size by at least MEMORY_GROWTH_LINEAR_STEP bytes. - // 4. Max size for the heap is capped at 2048MB-WASM_PAGE_SIZE, or by MAXIMUM_MEMORY, or by ASAN limit, depending on which is smallest - // 5. If we were unable to allocate as much memory, it may be due to over-eager decision to excessively reserve due to (3) above. + // 2b. If MEMORY_GROWTH_LINEAR_STEP != -1, excessively resize the heap linearly: increase the heap size by at least MEMORY_GROWTH_LINEAR_STEP bytes. + // 3. Max size for the heap is capped at 2048MB-WASM_PAGE_SIZE, or by MAXIMUM_MEMORY, or by ASAN limit, depending on which is smallest + // 4. If we were unable to allocate as much memory, it may be due to over-eager decision to excessively reserve due to (3) above. // Hence if an allocation fails, cut down on the amount of excess growth, in an attempt to succeed to perform a smaller allocation. // A limit was set for how much we can grow. We should not exceed that // (the wasm binary specifies it, so if we tried, we'd fail anyhow). + // In CAN_ADDRESS_2GB mode, stay one Wasm page short of 4GB: while e.g. Chrome is able to allocate full 4GB Wasm memories, the size will wrap + // back to 0 bytes in Wasm side for any code that deals with heap sizes, which would require special casing all heap size related code to treat + // 0 specially. var maxHeapSize = 2147483648; if (requestedSize > maxHeapSize) { err('Cannot enlarge memory, asked to go up to ' + requestedSize + ' bytes, but the limit is ' + maxHeapSize + ' bytes!'); return false; } - var minHeapSize = 16777216; - // Loop through potential heap size increases. If we attempt a too eager reservation that fails, cut down on the // attempted size and reserve a smaller bump instead. (max 3 times, chosen somewhat arbitrarily) for(var cutDown = 1; cutDown <= 4; cutDown *= 2) { @@ -1810,7 +1832,7 @@ var ASM_CONSTS = { // but limit overreserving (default to capping at +96MB overgrowth at most) overGrownHeapSize = Math.min(overGrownHeapSize, requestedSize + 100663296 ); - var newSize = Math.min(maxHeapSize, alignUp(Math.max(minHeapSize, requestedSize, overGrownHeapSize), 65536)); + var newSize = Math.min(maxHeapSize, alignUp(Math.max(requestedSize, overGrownHeapSize), 65536)); var replacement = emscripten_realloc_buffer(newSize); if (replacement) { @@ -2006,22 +2028,6 @@ var ASM_CONSTS = { return 0; } - var _emscripten_get_now;if (ENVIRONMENT_IS_NODE) { - _emscripten_get_now = function() { - var t = process['hrtime'](); - return t[0] * 1e3 + t[1] / 1e6; - }; - } else if (typeof dateNow !== 'undefined') { - _emscripten_get_now = dateNow; - } else _emscripten_get_now = function() { return performance.now(); } - ; - function _emscripten_thread_sleep(msecs) { - var start = _emscripten_get_now(); - while (_emscripten_get_now() - start < msecs) { - // Do nothing. - } - } - function __webgl_enable_ANGLE_instanced_arrays(ctx) { // Extension available in WebGL 1 from Firefox 26 and Google Chrome 30 onwards. Core feature in WebGL 2. var ext = ctx.getExtension('ANGLE_instanced_arrays'); @@ -2516,6 +2522,26 @@ var ASM_CONSTS = { return id; } + function _glDeleteBuffers(n, buffers) { + for (var i = 0; i < n; i++) { + var id = HEAP32[(((buffers)+(i*4))>>2)]; + var buffer = GL.buffers[id]; + + // From spec: "glDeleteBuffers silently ignores 0's and names that do not + // correspond to existing buffer objects." + if (!buffer) continue; + + GLctx.deleteBuffer(buffer); + buffer.name = 0; + GL.buffers[id] = null; + + if (id == GLctx.currentArrayBufferBinding) GLctx.currentArrayBufferBinding = 0; + if (id == GLctx.currentElementArrayBufferBinding) GLctx.currentElementArrayBufferBinding = 0; + if (id == GLctx.currentPixelPackBufferBinding) GLctx.currentPixelPackBufferBinding = 0; + if (id == GLctx.currentPixelUnpackBufferBinding) GLctx.currentPixelUnpackBufferBinding = 0; + } + } + function _glDeleteProgram(id) { if (!id) return; var program = GL.programs[id]; @@ -2540,6 +2566,14 @@ var ASM_CONSTS = { GL.shaders[id] = null; } + function _glDeleteVertexArrays(n, vaos) { + for (var i = 0; i < n; i++) { + var id = HEAP32[(((vaos)+(i*4))>>2)]; + GLctx['deleteVertexArray'](GL.vaos[id]); + GL.vaos[id] = null; + } + } + function _glDepthFunc(x0) { GLctx['depthFunc'](x0) } function _glDepthMask(flag) { @@ -2821,10 +2855,10 @@ function intArrayToString(array) { var asmLibraryArg = { "abort": _abort, "emscripten_memcpy_big": _emscripten_memcpy_big, + "emscripten_request_animation_frame_loop": _emscripten_request_animation_frame_loop, "emscripten_resize_heap": _emscripten_resize_heap, "emscripten_set_canvas_element_size": _emscripten_set_canvas_element_size, "emscripten_set_click_callback_on_thread": _emscripten_set_click_callback_on_thread, - "emscripten_thread_sleep": _emscripten_thread_sleep, "emscripten_webgl_create_context": _emscripten_webgl_create_context, "emscripten_webgl_init_context_attributes": _emscripten_webgl_init_context_attributes, "emscripten_webgl_make_context_current": _emscripten_webgl_make_context_current, @@ -2839,8 +2873,10 @@ var asmLibraryArg = { "glCompileShader": _glCompileShader, "glCreateProgram": _glCreateProgram, "glCreateShader": _glCreateShader, + "glDeleteBuffers": _glDeleteBuffers, "glDeleteProgram": _glDeleteProgram, "glDeleteShader": _glDeleteShader, + "glDeleteVertexArrays": _glDeleteVertexArrays, "glDepthFunc": _glDepthFunc, "glDepthMask": _glDepthMask, "glDrawArrays": _glDrawArrays, @@ -2869,18 +2905,12 @@ var ___wasm_call_ctors = Module["___wasm_call_ctors"] = createExportWrapper("__w var _main = Module["_main"] = createExportWrapper("main"); /** @type {function(...*):?} */ -var _usleep = Module["_usleep"] = createExportWrapper("usleep"); - -/** @type {function(...*):?} */ var ___errno_location = Module["___errno_location"] = createExportWrapper("__errno_location"); /** @type {function(...*):?} */ var _fflush = Module["_fflush"] = createExportWrapper("fflush"); /** @type {function(...*):?} */ -var _emscripten_main_thread_process_queued_calls = Module["_emscripten_main_thread_process_queued_calls"] = createExportWrapper("emscripten_main_thread_process_queued_calls"); - -/** @type {function(...*):?} */ var stackSave = Module["stackSave"] = createExportWrapper("stackSave"); /** @type {function(...*):?} */ @@ -2974,6 +3004,8 @@ if (!Object.getOwnPropertyDescriptor(Module, "ENV")) Module["ENV"] = function() if (!Object.getOwnPropertyDescriptor(Module, "ERRNO_CODES")) Module["ERRNO_CODES"] = function() { abort("'ERRNO_CODES' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; if (!Object.getOwnPropertyDescriptor(Module, "ERRNO_MESSAGES")) Module["ERRNO_MESSAGES"] = function() { abort("'ERRNO_MESSAGES' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; if (!Object.getOwnPropertyDescriptor(Module, "setErrNo")) Module["setErrNo"] = function() { abort("'setErrNo' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; +if (!Object.getOwnPropertyDescriptor(Module, "readSockaddr")) Module["readSockaddr"] = function() { abort("'readSockaddr' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; +if (!Object.getOwnPropertyDescriptor(Module, "writeSockaddr")) Module["writeSockaddr"] = function() { abort("'writeSockaddr' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; if (!Object.getOwnPropertyDescriptor(Module, "DNS")) Module["DNS"] = function() { abort("'DNS' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; if (!Object.getOwnPropertyDescriptor(Module, "getHostByName")) Module["getHostByName"] = function() { abort("'getHostByName' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; if (!Object.getOwnPropertyDescriptor(Module, "GAI_ERRNO_MESSAGES")) Module["GAI_ERRNO_MESSAGES"] = function() { abort("'GAI_ERRNO_MESSAGES' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; @@ -3337,8 +3369,6 @@ var shouldRunNow = true; if (Module['noInitialRun']) shouldRunNow = false; -noExitRuntime = true; - run(); diff --git a/frontend/2d/_collisions/pill_line/dist/output.wasm b/frontend/2d/_collisions/pill_line/dist/output.wasm Binary files differindex 56d07cf..be1afc5 100755 --- a/frontend/2d/_collisions/pill_line/dist/output.wasm +++ b/frontend/2d/_collisions/pill_line/dist/output.wasm diff --git a/frontend/2d/_collisions/pill_line/main.cpp b/frontend/2d/_collisions/pill_line/main.cpp index 6f85ccc..321a4ba 100644 --- a/frontend/2d/_collisions/pill_line/main.cpp +++ b/frontend/2d/_collisions/pill_line/main.cpp @@ -2,6 +2,8 @@ #include "../../../shared_cpp/types.h" #include "../../../shared_cpp/WebglContext.h" #include "../../../shared_cpp/mathlib.h" +#include "../../../shared_cpp/MainLoop.h" +#include <cstdio> #include <emscripten/html5.h> #include <unistd.h> #include <pthread.h> @@ -10,49 +12,42 @@ typedef OrthographicShape<3> TriangleShape; EM_BOOL onPlayClicked(int eventType, const EmscriptenMouseEvent* mouseEvent, void* userData); EM_BOOL onStopClicked(int eventType, const EmscriptenMouseEvent* mouseEvent, void* userData); -EM_BOOL update(double time, void* userData); -void *execute(void* vargp); +EM_BOOL update(float time, void* userData); + +WebglContext context; +OrthographicRenderer renderer; +TriangleShape shape; +MainLoop mainLoop; int main() { - WebglContext context; context.init("#gl_canvas"); - - OrthographicRenderer renderer; - renderer.load(); - - TriangleShape shape; - shape.vertices[0] = { Vector2 { -1, -1 }, Vector4 { 1, 0, 0, 1 } }; - shape.vertices[1] = { Vector2 { 0, 1 }, Vector4{ 0, 1, 0, 1 } }; - shape.vertices[2] = { Vector2 { 1, -1 }, Vector4 { 0, 0, 1, 1 } }; - - shape.load(&renderer); - emscripten_set_click_callback("#gl_canvas_play", NULL, false, onPlayClicked); emscripten_set_click_callback("#gl_canvas_stop", NULL, false, onStopClicked); - - renderer.render(); - shape.render(&renderer); - return 0; } EM_BOOL onPlayClicked(int eventType, const EmscriptenMouseEvent* mouseEvent, void* userData) { + printf("Play clicked\n"); + + renderer.load(); + shape.vertices[0] = { Vector2 { -1, -1 }, Vector4 { 1, 0, 0, 1 } }; + shape.vertices[1] = { Vector2 { 0, 1 }, Vector4{ 0, 1, 0, 1 } }; + shape.vertices[2] = { Vector2 { 1, -1 }, Vector4 { 0, 0, 1, 1 } }; + shape.load(&renderer); + mainLoop.run(update); return true; } EM_BOOL onStopClicked(int eventType, const EmscriptenMouseEvent* mouseEvent, void* userData) { + printf("Stop clicked\n"); + mainLoop.stop(); + shape.unload(); + renderer.unload(); return true; } -EM_BOOL run(int eventType, const EmscriptenMouseEvent* mouseEvent, void* userData) { - pthread_t thread_id; - pthread_create(&thread_id, NULL, execute, NULL); - return true; -} - -void *execute(void* vargp) { - while (true) { - sleep(1); - printf("Executing\n"); - } +EM_BOOL update(float deltaTimeSeconds, void* userData) { + renderer.render(); + shape.render(&renderer); + return true; }
\ No newline at end of file diff --git a/frontend/roadmap.html b/frontend/roadmap.html index 9daa3ed..4543028 100644 --- a/frontend/roadmap.html +++ b/frontend/roadmap.html @@ -50,7 +50,7 @@ <ul> <li class="done">Orthographic rendering basics</li> <li class="done">Uniform build Process for WebAssembly</li> - <li>WASM Framework with simulation loop</li> + <li class="done">WASM Framework with simulation loop</li> </ul> <hr/> <h1>2D Collisions with Descriptions</h1> diff --git a/frontend/shared_cpp/MainLoop.cpp b/frontend/shared_cpp/MainLoop.cpp new file mode 100644 index 0000000..82a24b5 --- /dev/null +++ b/frontend/shared_cpp/MainLoop.cpp @@ -0,0 +1,30 @@ +#include "MainLoop.h" +#include <cstdio> +#include <cstdlib> + +EM_BOOL loop(double time, void* loop) { + MainLoop* mainLoop = (MainLoop*) loop; + if (!mainLoop->isRunning) { + return false; + } + + if (mainLoop->lastTime == 0) { + mainLoop->lastTime = time; + return true; + } + + long deltaTime = time - mainLoop->lastTime; + mainLoop->lastTime = time; + mainLoop->elapsedTime += deltaTime; + mainLoop->numFrames++; + float deltaTimeSeconds = static_cast<float>(deltaTime) / 1000.f; + + if (mainLoop->elapsedTime >= 1000.0) { + printf("FPS: %d\n", mainLoop->numFrames); + + mainLoop->elapsedTime = 0.0; + mainLoop->numFrames = 0; + } + + return mainLoop->updateFunc(deltaTimeSeconds, NULL); +}
\ No newline at end of file diff --git a/frontend/shared_cpp/MainLoop.h b/frontend/shared_cpp/MainLoop.h new file mode 100644 index 0000000..7300f6b --- /dev/null +++ b/frontend/shared_cpp/MainLoop.h @@ -0,0 +1,29 @@ +#pragma once + +#include <emscripten.h> +#include <emscripten/html5.h> +#include <GLES2/gl2.h> +#include <EGL/egl.h> + +EM_BOOL loop(double time, void* loop); + +struct MainLoop { + bool isRunning = false; + double lastTime = 0, elapsedTime = 0; + int numFrames = 0; + EM_BOOL (*updateFunc)(float dtSeconds, void *userData); + + void run(EM_BOOL (*cb)(float dtSeconds, void *userData)) { + isRunning = true; + lastTime = 0; + elapsedTime = 0; + numFrames = 0; + updateFunc = cb; + + emscripten_request_animation_frame_loop(loop, this); + } + + void stop() { + isRunning = false; + } +};
\ No newline at end of file diff --git a/frontend/shared_cpp/OrthographicRenderer.cpp b/frontend/shared_cpp/OrthographicRenderer.cpp index d160ecc..b6bd5b6 100644 --- a/frontend/shared_cpp/OrthographicRenderer.cpp +++ b/frontend/shared_cpp/OrthographicRenderer.cpp @@ -43,5 +43,7 @@ void OrthographicRenderer::render() { } void OrthographicRenderer::unload() { + glClearColor(0.2f, 0.3f, 0.3f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); glDeleteProgram(shader); } diff --git a/frontend/shared_cpp/WebglContext.h b/frontend/shared_cpp/WebglContext.h index c8a9480..1ea1c91 100644 --- a/frontend/shared_cpp/WebglContext.h +++ b/frontend/shared_cpp/WebglContext.h @@ -1,10 +1,13 @@ #pragma once +#include "types.h" #include <emscripten.h> #include <emscripten/html5.h> #include <GLES2/gl2.h> #include <EGL/egl.h> struct WebglContext { + EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context; + void init(const char* query, int width = 640, int height = 480) { emscripten_set_canvas_element_size( query, width, height); @@ -17,6 +20,9 @@ struct WebglContext { context = emscripten_webgl_create_context(query, &attrs); makeCurrentContext(); + + glClearColor(0.2f, 0.3f, 0.3f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); }; void makeCurrentContext() { @@ -26,6 +32,4 @@ struct WebglContext { void destroy() { emscripten_webgl_destroy_context(context); } - - EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context; -}; +};
\ No newline at end of file |