diff options
Diffstat (limited to 'frontend/_wasm/intro/intro.cpp')
-rw-r--r-- | frontend/_wasm/intro/intro.cpp | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/frontend/_wasm/intro/intro.cpp b/frontend/_wasm/intro/intro.cpp new file mode 100644 index 0000000..63c80ef --- /dev/null +++ b/frontend/_wasm/intro/intro.cpp @@ -0,0 +1,223 @@ +#include <cstdio> +#include <cstdlib> +#include <cstring> +#include <sys/time.h> +#include <emscripten.h> +#include <emscripten/html5.h> +#include <GLES2/gl2.h> +#include <EGL/egl.h> + +#include "mathlib.h" +#include "Shader.h" + +// Shader code inlined +const char* orthographicVertex = +"attribute vec2 position; \n" +"attribute vec4 color; \n" +"uniform mat4 projection; \n" +"uniform mat4 model; \n" +"varying lowp vec4 VertexColor; \n" +"void main() { \n" +" vec4 fragmentPosition = projection * model * vec4(position, 1, 1); \n" +" gl_Position = fragmentPosition; \n" +" VertexColor = color; \n" +"}"; + +const char* orthographicFragment = +"varying lowp vec4 VertexColor; \n" +"void main() { \n" +" gl_FragColor = VertexColor; \n" +"}"; + + +struct OrthographicProgramData { + GLuint shader; + + struct { + int position; + int color; + } attributes; + + struct { + int projection; + int model; + } uniformVariables; +}; + +struct OrthographicVertex { + Vector2 position; + Vector4 color; +}; + +// Create a triangle +struct TriangleObject { + OrthographicVertex vertices[3]; + Vector2 velocity; + Vector2 position; + GLuint mVao; + GLuint mVbo; + Mat4x4 model; + + void initialize(OrthographicProgramData* programData) { + useShader(programData->shader); + + glGenVertexArrays(1, &mVao); + glBindVertexArray(mVao); + + glGenBuffers(1, &mVbo); + glBindBuffer(GL_ARRAY_BUFFER, mVbo); + glBufferData(GL_ARRAY_BUFFER, 3 * sizeof(OrthographicVertex), &vertices[0], GL_STATIC_DRAW); + + glEnableVertexAttribArray(programData->attributes.position); + glVertexAttribPointer(programData->attributes.position, 2, GL_FLOAT, GL_FALSE, sizeof(OrthographicVertex), (GLvoid *)0); + + glEnableVertexAttribArray(programData->attributes.color); + glVertexAttribPointer(programData->attributes.color, 4, GL_FLOAT, GL_FALSE, sizeof(OrthographicVertex), (GLvoid *)offsetof(OrthographicVertex, color)); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); + } + + void render(OrthographicProgramData* programData) { + setShaderMat4(programData->uniformVariables.model, model); + + glBindVertexArray(mVao); + glDrawArrays(GL_TRIANGLES, 0, 3); + glBindVertexArray(0); + } + +}; + +struct Scene { + Mat4x4 projection; + TriangleObject triangleObject; + OrthographicProgramData programData; + bool isTerminated = false; +}; + +long long timeInMilliseconds(void) { + struct timeval tv; + + gettimeofday(&tv,NULL); + return (((long long)tv.tv_sec)*1000)+(tv.tv_usec/1000); +} + +long elapsedTime = 0; +long lastTime = 0; +int numFrames = 0; + +EM_BOOL update(double time, void* userData); +EM_BOOL runScene(int eventType, const EmscriptenMouseEvent* mouseEvent, void* userData); +EM_BOOL terminateScene(int eventType, const EmscriptenMouseEvent* mouseEvent, void* userData); + +int main() { + printf("Initializing the canvas...\n"); + emscripten_set_canvas_element_size( "#wasm_canvas", 640, 480 ); + + EmscriptenWebGLContextAttributes attrs; + emscripten_webgl_init_context_attributes(&attrs); + + attrs.enableExtensionsByDefault = 1; + attrs.majorVersion = 3; + attrs.minorVersion = 0; + + EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context = emscripten_webgl_create_context( "#wasm_canvas", &attrs ); + + if (!context) + { + attrs.majorVersion = 1; + context = emscripten_webgl_create_context( "#wasm_canvas", &attrs ); + if (context) printf("Skipping test: WebGL 3.0 is not available.\n"); + else printf("Test failed: WebGL is not available!\n"); + return 0; + } + emscripten_webgl_make_context_current(context); + printf("Canvas ready.\n"); + + emscripten_set_click_callback("#wasm_canvas_play_button", NULL, false, runScene); + emscripten_set_click_callback("#wasm_canvas_stop_button", NULL, false, terminateScene); + return EXIT_SUCCESS; +} + +Scene scene; + +EM_BOOL runScene(int eventType, const EmscriptenMouseEvent* mouseEvent, void* userData) { + scene.programData = OrthographicProgramData(); + printf("Compiling shaders...\n"); + scene.programData.shader = loadShader(orthographicVertex, orthographicFragment); + printf("Shaders compiled.\n"); + + + printf("Initializing scene...\n"); + useShader(scene.programData.shader); + + scene.programData.attributes.position = getShaderAttribute(scene.programData.shader, "position"); + scene.programData.attributes.color = getShaderAttribute(scene.programData.shader, "color"); + scene.programData.uniformVariables.projection = getShaderUniform(scene.programData.shader, "projection"); + scene.programData.uniformVariables.model = getShaderUniform(scene.programData.shader, "model"); + + scene.triangleObject = TriangleObject(); + scene.triangleObject.vertices[0] = { Vector2 { -100, -50 }, Vector4 { 1.f, 0.f, 0.f, 1.f }}; + scene.triangleObject.vertices[1] = { Vector2 { 0, 50 }, Vector4 { 0.f, 1.f, 0.f, 1.f }}; + scene.triangleObject.vertices[2] = { Vector2 { 100, -50 }, Vector4 { 0.f, 0.f, 1.f, 1.f }}; + scene.triangleObject.position = { 320.f, 480.f - 100.f }; + scene.triangleObject.initialize(&scene.programData); + + scene.projection = Mat4x4().getOrthographicMatrix(0, 640, 0, 480); + scene.isTerminated = false; + printf("Scene initialized.\n"); + + emscripten_request_animation_frame_loop(update, &scene); + return true; +} + +EM_BOOL update(double time, void* userData) { + Scene* scene = (Scene*)userData; + if (scene->isTerminated) { + return false; + } + + if (lastTime == 0) { + lastTime = time; + return true; + } + + long deltaTime = time - lastTime; + lastTime = time; + elapsedTime += deltaTime; + numFrames++; + + if (elapsedTime >= 1000.0) { + printf("Frames Per Second: %d\n", numFrames); + numFrames = 0; + elapsedTime = 0.0; + } + + float deltaTimeSeconds = static_cast<float>(deltaTime) / 1000.f; + + // Update + scene->triangleObject.velocity = scene->triangleObject.velocity + Vector2 { 0, static_cast<float>(-9.8 * deltaTimeSeconds) }; + scene->triangleObject.position = scene->triangleObject.position + scene->triangleObject.velocity * deltaTimeSeconds; + scene->triangleObject.model = Mat4x4().translateByVec2(scene->triangleObject.position); + + // Render + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LEQUAL); + glDepthMask(GL_TRUE); + glClearColor(0.2f, 0.3f, 0.3f, 1.0f); + glClearDepth(1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + useShader(scene->programData.shader); + setShaderMat4(scene->programData.uniformVariables.projection, scene->projection); + scene->triangleObject.render(&scene->programData); + + return true; +} + +EM_BOOL terminateScene(int eventType, const EmscriptenMouseEvent* mouseEvent, void* userData) { + scene.isTerminated = true; + glDeleteVertexArrays(1, &scene.triangleObject.mVao); + glDeleteBuffers(1, &scene.triangleObject.mVbo); + glDeleteProgram(scene.programData.shader); + return true; +} |