diff options
Diffstat (limited to 'shared_cpp')
-rw-r--r-- | shared_cpp/MainLoop.cpp | 31 | ||||
-rw-r--r-- | shared_cpp/MainLoop.h | 29 | ||||
-rw-r--r-- | shared_cpp/OrthographicRenderer.cpp | 87 | ||||
-rw-r--r-- | shared_cpp/OrthographicRenderer.h | 43 | ||||
-rw-r--r-- | shared_cpp/Shader.cpp | 61 | ||||
-rw-r--r-- | shared_cpp/Shader.h | 63 | ||||
-rw-r--r-- | shared_cpp/WebglContext.h | 39 | ||||
-rw-r--r-- | shared_cpp/WebglHelper.h | 6 | ||||
-rw-r--r-- | shared_cpp/mathlib.cpp | 11 | ||||
-rw-r--r-- | shared_cpp/mathlib.h | 227 | ||||
-rw-r--r-- | shared_cpp/types.h | 18 |
11 files changed, 615 insertions, 0 deletions
diff --git a/shared_cpp/MainLoop.cpp b/shared_cpp/MainLoop.cpp new file mode 100644 index 0000000..09aa643 --- /dev/null +++ b/shared_cpp/MainLoop.cpp @@ -0,0 +1,31 @@ +#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; + } + + mainLoop->updateFunc(deltaTimeSeconds, NULL); + return true; +}
\ No newline at end of file diff --git a/shared_cpp/MainLoop.h b/shared_cpp/MainLoop.h new file mode 100644 index 0000000..2573bb8 --- /dev/null +++ b/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; + void (*updateFunc)(float dtSeconds, void *userData); + + void run(void (*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/shared_cpp/OrthographicRenderer.cpp b/shared_cpp/OrthographicRenderer.cpp new file mode 100644 index 0000000..21c13a1 --- /dev/null +++ b/shared_cpp/OrthographicRenderer.cpp @@ -0,0 +1,87 @@ +#include "OrthographicRenderer.h" +#include "WebglContext.h" +#include "mathlib.h" + +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" +"}"; + +void OrthographicRenderer::load(WebglContext* context) { + printf("Compiling orthographic shader...\n"); + shader = loadShader(orthographicVertex, orthographicFragment); + + useShader(shader); + attributes.position = getShaderAttribute(shader, "position"); + attributes.color = getShaderAttribute(shader, "color"); + uniforms.projection = getShaderUniform(shader, "projection"); + uniforms.model = getShaderUniform(shader, "model"); + projection = Mat4x4().getOrthographicMatrix(0, context->width, 0, context->height); + + printf("Orthographic shader compiled.\n"); +} + +void OrthographicRenderer::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(shader); + setShaderMat4(uniforms.projection, projection); +} + +void OrthographicRenderer::unload() { + glClearColor(0.2f, 0.3f, 0.3f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + glDeleteProgram(shader); +} + + +void OrthographicShape::load(OrthographicVertex* inVertices, uint32 inNumVertices, OrthographicRenderer* renderer) { + numVertices = inNumVertices; + useShader(renderer->shader); + + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); + + glGenBuffers(1, &vbo); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBufferData(GL_ARRAY_BUFFER, inNumVertices * sizeof(OrthographicVertex), &inVertices[0], GL_STATIC_DRAW); + + glEnableVertexAttribArray(renderer->attributes.position); + glVertexAttribPointer(renderer->attributes.position, 2, GL_FLOAT, GL_FALSE, sizeof(OrthographicVertex), (GLvoid *)0); + + glEnableVertexAttribArray(renderer->attributes.color); + glVertexAttribPointer(renderer->attributes.color, 4, GL_FLOAT, GL_FALSE, sizeof(OrthographicVertex), (GLvoid *)offsetof(OrthographicVertex, color)); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); +} + +void OrthographicShape::render(OrthographicRenderer* renderer, GLenum drawType) { + setShaderMat4(renderer->uniforms.model, model); + + glBindVertexArray(vao); + glDrawArrays(drawType, 0, numVertices); + glBindVertexArray(0); +} + +void OrthographicShape::unload() { + glDeleteVertexArrays(1, &vao); + glDeleteBuffers(1, &vbo); +}
\ No newline at end of file diff --git a/shared_cpp/OrthographicRenderer.h b/shared_cpp/OrthographicRenderer.h new file mode 100644 index 0000000..cef5305 --- /dev/null +++ b/shared_cpp/OrthographicRenderer.h @@ -0,0 +1,43 @@ +#pragma once + +#include "WebglContext.h" +#include "types.h" +#include "Shader.h" +#include "mathlib.h" + +struct WebglContext; + +struct OrthographicRenderer { + Mat4x4 projection; + uint32 shader; + + struct { + int32 position; + int32 color; + } attributes; + + struct { + int32 projection; + int32 model; + } uniforms; + + void load(WebglContext* context); + void render(); + void unload(); +}; + +struct OrthographicVertex { + Vector2 position; + Vector4 color; +}; + +struct OrthographicShape { + uint32 vao; + uint32 vbo; + uint32 numVertices = 0; + Mat4x4 model; + + void load(OrthographicVertex* vertices, uint32 numVertices, OrthographicRenderer* renderer); + void render(OrthographicRenderer* renderer, GLenum drawType = GL_TRIANGLES); + void unload(); +};
\ No newline at end of file diff --git a/shared_cpp/Shader.cpp b/shared_cpp/Shader.cpp new file mode 100644 index 0000000..5f2b00e --- /dev/null +++ b/shared_cpp/Shader.cpp @@ -0,0 +1,61 @@ +#include "Shader.h" +#include <string> + +GLuint loadIndividualShader(GLenum shaderType, const GLchar* cCode) { + GLuint shader = glCreateShader(shaderType); + glShaderSource(shader, 1, &cCode, 0); + glCompileShader(shader); + GLint success; + glGetShaderiv(shader, GL_COMPILE_STATUS, &success); + if (!success) { + GLchar infoLog[512]; + glGetShaderInfoLog(shader, 512, 0, infoLog); + printf("Failed to load shader: %s, Shader =%s\n", infoLog, cCode); + return 0; + } + + return shader; +} + +void attachShaders(Shader& retVal, const GLchar* vertexShader, const GLchar* fragmentShader) { + GLuint vertex = 0, fragment = 0, geometry = 0; + if (vertexShader) { + vertex = loadIndividualShader(GL_VERTEX_SHADER, vertexShader); + glAttachShader(retVal, vertex); + } + + if (fragmentShader) { + fragment = loadIndividualShader(GL_FRAGMENT_SHADER, fragmentShader); + glAttachShader(retVal, fragment); + } + + glLinkProgram(retVal); + GLint isLinked = 0; + glGetProgramiv(retVal, GL_LINK_STATUS, (int*)&isLinked); + if (isLinked == GL_FALSE) { + GLint maxLength = 0; + glGetProgramiv(retVal, GL_INFO_LOG_LENGTH, &maxLength); + + // The maxLength includes the NULL character + GLchar* infoLog = new GLchar[maxLength]; + glGetProgramInfoLog(retVal, maxLength, &maxLength, infoLog); + glDeleteProgram(retVal); + printf("Error. Could not initialize shader with vertex=%s, error=%s\n", vertexShader, infoLog); + delete []infoLog; + } + + if (vertexShader) + glDeleteShader(vertex); + if (fragmentShader) + glDeleteShader(fragment); +} + +Shader loadShader(const GLchar* vertexShader, const GLchar* fragmentShader) { + Shader retVal; + retVal = glCreateProgram(); + + attachShaders(retVal, vertexShader, fragmentShader); + useShader(retVal); + + return retVal; +} diff --git a/shared_cpp/Shader.h b/shared_cpp/Shader.h new file mode 100644 index 0000000..6ee9981 --- /dev/null +++ b/shared_cpp/Shader.h @@ -0,0 +1,63 @@ +#pragma once + +#include <GL/glew.h> +#include <string> +#include <vector> +#include "mathlib.h" + +typedef GLuint Shader; + +Shader loadShader(const GLchar* vertexShader, const GLchar* fragmentShader); + +inline GLint getShaderUniform(const Shader& shader, const GLchar *name) { + GLint uid = glGetUniformLocation(shader, name); + if (uid < 0) { + return -1; + } + return uid; +} + +inline GLint getShaderAttribute(const Shader& shader, const GLchar *name) { + printf("Getting attribute for shader, name: %d, %s\n", shader, name); + GLint uid = glGetAttribLocation(shader, name); + if (uid < 0) { + return -1; + } + return uid; +} + +inline void useShader(const Shader& shader) { + glUseProgram(shader); +} + +inline void setShaderFloat(GLint location, GLfloat value) { + glUniform1f(location, value); +} + +inline void setShaderInt(GLint location, GLint value) { + glUniform1i(location, value); +} + +inline void setShaderUint(GLint location, GLuint value) { + glUniform1ui(location, value); +} + +inline void setShaderVec2(GLint location, const Vector2& value) { + glUniform2f(location, value.x, value.y); +} + +inline void setShaderMat4(GLint location, const Mat4x4& matrix) { + glUniformMatrix4fv(location, 1, GL_FALSE, matrix.m); +} + +inline void setShaderBVec3(GLint location, bool first, bool second, bool third) { + glUniform3i(location, first, second, third); +} + +inline void setShaderBVec4(GLint location, bool first, bool second, bool third, bool fourth) { + glUniform4i(location, first, second, third, fourth); +} + +inline void setShaderBool(GLint location, bool value) { + glUniform1i(location, value); +}
\ No newline at end of file diff --git a/shared_cpp/WebglContext.h b/shared_cpp/WebglContext.h new file mode 100644 index 0000000..017498f --- /dev/null +++ b/shared_cpp/WebglContext.h @@ -0,0 +1,39 @@ +#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; + int width = 640; + int height = 480; + + void init(const char* query, int inWidth = 640, int inHeight = 480) { + width = inWidth; + height = inHeight; + emscripten_set_canvas_element_size( query, width, height); + + EmscriptenWebGLContextAttributes attrs; + emscripten_webgl_init_context_attributes(&attrs); + + attrs.enableExtensionsByDefault = 1; + attrs.majorVersion = 3; + attrs.minorVersion = 0; + + context = emscripten_webgl_create_context(query, &attrs); + makeCurrentContext(); + + glClearColor(0.2f, 0.3f, 0.3f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + }; + + void makeCurrentContext() { + emscripten_webgl_make_context_current(context); + }; + + void destroy() { + emscripten_webgl_destroy_context(context); + } +};
\ No newline at end of file diff --git a/shared_cpp/WebglHelper.h b/shared_cpp/WebglHelper.h new file mode 100644 index 0000000..dbdb23f --- /dev/null +++ b/shared_cpp/WebglHelper.h @@ -0,0 +1,6 @@ +#pragma once +#include "mathlib.h" + +struct OrthographicRenderer; + +void render2DArrow(Vector2 start, Vector2 end, OrthographicRenderer* renderer); diff --git a/shared_cpp/mathlib.cpp b/shared_cpp/mathlib.cpp new file mode 100644 index 0000000..8222d00 --- /dev/null +++ b/shared_cpp/mathlib.cpp @@ -0,0 +1,11 @@ +#include "mathlib.h" +#include <cstdlib> + +Vector2 getRandomNormalVector2() { + Vector2 retval = { + static_cast<float>(rand()) / static_cast<float>(RAND_MAX), + static_cast<float>(rand()) / static_cast<float>(RAND_MAX) + }; + + return retval.normalize(); +} diff --git a/shared_cpp/mathlib.h b/shared_cpp/mathlib.h new file mode 100644 index 0000000..3ed61cd --- /dev/null +++ b/shared_cpp/mathlib.h @@ -0,0 +1,227 @@ +#pragma once +#include <cstdio> +#include <cstdlib> +#include <cstring> +#include <cmath> + +#define MAX(x, y) (((x) > (y)) ? (x) : (y)) +#define MIN(x, y) (((x) < (y)) ? (x) : (y)) +#define ABS(x) (x < 0 ? -x : x) + +struct Vector2 { + float x = 0; + float y = 0; + + Vector2 operator+(Vector2 other) { + return { x + other.x, y + other.y }; + } + + Vector2& operator+=(Vector2 other) { + x += other.x; + y += other.y; + return *this; + } + + Vector2 operator-(Vector2 other) { + return { x - other.x, y - other.y }; + } + + Vector2 operator*(float s) { + return { x * s, y * s }; + } + + Vector2 operator/(float s) { + return { x / s, y / s }; + } + + float dot(Vector2 other) { + return x * other.x + y * other.y; + } + + float length() { + return sqrtf(x * x + y * y); + } + + Vector2 normalize() { + float len = length(); + float inverseLength = len == 0 ? 1.0 : 1.0 / len; + + return { x * inverseLength, y * inverseLength }; + } + + Vector2 negate() { + return { -x, -y }; + } + + Vector2 getPerp() { + return { y, -x }; + } + + Vector2 rotate(float angle) { + return { + x * cosf(angle) - y * sinf(angle), + x * sinf(angle) + y * cosf(angle) + }; + } + + void printDebug(const char* name) { + printf("%s=Vector2(%f, %f)\n", name, x, y); + } + + float determinant(Vector2 other) { + // + // [ a b ] + // [ c d ] + // + // [ x other.x ] + // [ y other.y ] + // + // det = a * d - b * c + // det = x * other.y - other.x * y + // + return x * other.y - other.x * y; + } +}; + +struct Vector3 { + float x = 0.f; + float y = 0.f; + float z = 0.f; +}; + +struct Vector4 { + float x = 0.f; + float y = 0.f; + float z = 0.f; + float w = 0.f; + + float length() { + return sqrtf(x * x + y * y + z * z + w * w); + } + + Vector4 normalize() { + float len = length(); + float inverseLength = len == 0 ? 1.0 : 1.0 / len; + + return { x * inverseLength, y * inverseLength, z * inverseLength, w * inverseLength }; + } + + Vector4 fromColor(float r, float g, float b, float a) { + float scale = 1.f / 255.f; + return { r * scale, g * scale, b * scale, a * scale }; + } + + Vector4 toNormalizedColor() { + return fromColor(x, y, z, w); + } +}; + +struct Mat4x4 { + float m[16] = { + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 + }; + + Mat4x4 copy() { + Mat4x4 result; + memcpy(result.m, m, sizeof(float) * 16); + return result; + } + + Mat4x4 scale(Vector3 v) { + Mat4x4 result = copy(); + result.m[0] = result.m[0] * v.x; + result.m[5] = result.m[5] *v.y; + result.m[10] = result.m[10] * v.z; + return result; + } + + Mat4x4 translate(Vector3 v) { + Mat4x4 result = copy(); + result.m[12] += v.x; + result.m[13] += v.y; + result.m[14] += v.z; + return result; + } + + Mat4x4 translateByVec2(Vector2 v) { + Mat4x4 result = copy(); + result.m[12] += v.x; + result.m[13] += v.y; + return result; + } + + Mat4x4 rotate2D(float angle) { + Mat4x4 result = copy(); + result.m[0] = cos(angle); + result.m[1] = -sin(angle); + result.m[4] = sin(angle); + result.m[5] = cos(angle); + return result; + } + + Vector2 multByVec2(Vector2 v) { + Vector4 vec4 = { v.x, v.y, 0.0, 1.0 }; + return { + vec4.x * m[0] + vec4.y * m[4] + vec4.z * m[8] + vec4.w * m[12], + vec4.x * m[1] + vec4.y * m[5] + vec4.z * m[9] + vec4.w * m[13] + }; + } + + Vector2 operator*(Vector2 v) { + return multByVec2(v); + } + + Mat4x4 getOrthographicMatrix(float left, float right, float bottom, float top) { + Mat4x4 result; + result.m[0] = 2.0 / (right - left); + result.m[5] = 2.0 / (top - bottom); + result.m[10] = 1.0; + result.m[12] = -(right + left) / (right - left); + result.m[13] = -(top + bottom) / (top - bottom); + return result; + } + + Mat4x4 inverse() { + Mat4x4 inv; + + inv.m[0] = m[5] * m[10] * m[15] - m[5] * m[11] * m[14] - m[9] * m[6] * m[15] + m[9] * m[7] * m[14] + m[13] * m[6] * m[11] - m[13] * m[7] * m[10]; + inv.m[4] = -m[4] * m[10] * m[15] + m[4] * m[11] * m[14] + m[8] * m[6] * m[15] - m[8] * m[7] * m[14] - m[12] * m[6] * m[11] + m[12] * m[7] * m[10]; + inv.m[8] = m[4] * m[9] * m[15] - m[4] * m[11] * m[13] - m[8] * m[5] * m[15] + m[8] * m[7] * m[13] + m[12] * m[5] * m[11] - m[12] * m[7] * m[9]; + inv.m[12] = -m[4] * m[9] * m[14] + m[4] * m[10] * m[13] + m[8] * m[5] * m[14] - m[8] * m[6] * m[13] - m[12] * m[5] * m[10] + m[12] * m[6] * m[9]; + inv.m[1] = -m[1] * m[10] * m[15] + m[1] * m[11] * m[14] + m[9] * m[2] * m[15] - m[9] * m[3] * m[14] - m[13] * m[2] * m[11] + m[13] * m[3] * m[10]; + inv.m[5] = m[0] * m[10] * m[15] - m[0] * m[11] * m[14] - m[8] * m[2] * m[15] + m[8] * m[3] * m[14] + m[12] * m[2] * m[11] - m[12] * m[3] * m[10]; + inv.m[9] = -m[0] * m[9] * m[15] + m[0] * m[11] * m[13] + m[8] * m[1] * m[15] - m[8] * m[3] * m[13] - m[12] * m[1] * m[11] + m[12] * m[3] * m[9]; + inv.m[13] = m[0] * m[9] * m[14] - m[0] * m[10] * m[13] - m[8] * m[1] * m[14] + m[8] * m[2] * m[13] + m[12] * m[1] * m[10] - m[12] * m[2] * m[9]; + inv.m[2] = m[1] * m[6] * m[15] - m[1] * m[7] * m[14] - m[5] * m[2] * m[15] + m[5] * m[3] * m[14] + m[13] * m[2] * m[7] - m[13] * m[3] * m[6]; + inv.m[6] = -m[0] * m[6] * m[15] + m[0] * m[7] * m[14] + m[4] * m[2] * m[15] - m[4] * m[3] * m[14] - m[12] * m[2] * m[7] + m[12] * m[3] * m[6]; + inv.m[10] = m[0] * m[5] * m[15] - m[0] * m[7] * m[13] - m[4] * m[1] * m[15] + m[4] * m[3] * m[13] + m[12] * m[1] * m[7] - m[12] * m[3] * m[5]; + inv.m[14] = -m[0] * m[5] * m[14] + m[0] * m[6] * m[13] + m[4] * m[1] * m[14] - m[4] * m[2] * m[13] - m[12] * m[1] * m[6] + m[12] * m[2] * m[5]; + inv.m[3] = -m[1] * m[6] * m[11] + m[1] * m[7] * m[10] + m[5] * m[2] * m[11] - m[5] * m[3] * m[10] - m[9] * m[2] * m[7] + m[9] * m[3] * m[6]; + inv.m[7] = m[0] * m[6] * m[11] - m[0] * m[7] * m[10] - m[4] * m[2] * m[11] + m[4] * m[3] * m[10] + m[8] * m[2] * m[7] - m[8] * m[3] * m[6]; + inv.m[11] = -m[0] * m[5] * m[11] + m[0] * m[7] * m[9] + m[4] * m[1] * m[11] - m[4] * m[3] * m[9] - m[8] * m[1] * m[7] + m[8] * m[3] * m[5]; + inv.m[15] = m[0] * m[5] * m[10] - m[0] * m[6] * m[9] - m[4] * m[1] * m[10] + m[4] * m[2] * m[9] + m[8] * m[1] * m[6] - m[8] * m[2] * m[5]; + + float det = m[0] * inv.m[0] + m[1] * inv.m[4] + m[2] * inv.m[8] + m[3] * inv.m[12]; + + if (det == 0) + return Mat4x4(); + + det = 1.f / det; + + for (int i = 0; i < 16; i++) + inv.m[i] = inv.m[i] * det; + + return inv; + } + + void print() { + printf("[ "); + for (int idx = 0; idx < 16; idx++) { + printf("%f, ", m[idx]); + } + printf(" ]\n"); + } +}; diff --git a/shared_cpp/types.h b/shared_cpp/types.h new file mode 100644 index 0000000..3739699 --- /dev/null +++ b/shared_cpp/types.h @@ -0,0 +1,18 @@ +#pragma once + +#include <cstdint> + +typedef int8_t int8; +typedef int16_t int16; +typedef int32_t int32; +typedef int64_t int64; + +typedef uint8_t uint8; +typedef uint16_t uint16; +typedef uint32_t uint32; +typedef unsigned long uint64; + +typedef float float32; +typedef double float64; + +#define PI 3.14159265358979323846
\ No newline at end of file |