summaryrefslogtreecommitdiff
path: root/frontend/_wasm/intro/intro.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'frontend/_wasm/intro/intro.cpp')
-rw-r--r--frontend/_wasm/intro/intro.cpp223
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;
+}