summaryrefslogtreecommitdiff
path: root/themes
diff options
context:
space:
mode:
authorMatthew Kosarek <mattkae@protonmail.com>2021-10-05 06:35:09 -0400
committerMatthew Kosarek <mattkae@protonmail.com>2021-10-05 06:35:09 -0400
commitd781d5a3c1ec6872361db2a15786dfc0db9780f3 (patch)
tree7e355a89bb0062cdd7692f3dae820a5e467aba9e /themes
parent9d33d175b5cd564e77bda07fcbce252477f7c40f (diff)
Working tree render, now just have to do the leaves
Diffstat (limited to 'themes')
-rw-r--r--themes/LeafParticleRender.cpp51
-rw-r--r--themes/LeafParticleRender.h35
-rw-r--r--themes/Renderer2d.cpp16
-rw-r--r--themes/Renderer2d.h2
-rw-r--r--themes/TreeShape.cpp159
-rw-r--r--themes/TreeShape.h112
-rw-r--r--themes/WebglContext.cpp1
-rw-r--r--themes/deprecated/TreeRenderer.cpp57
-rw-r--r--themes/deprecated/TreeRenderer.h36
-rw-r--r--themes/dist/output.js12
-rwxr-xr-xthemes/dist/output.wasmbin44887 -> 48362 bytes
-rw-r--r--themes/main.cpp1
-rw-r--r--themes/mathlib.cpp7
-rw-r--r--themes/mathlib.h2
14 files changed, 412 insertions, 79 deletions
diff --git a/themes/LeafParticleRender.cpp b/themes/LeafParticleRender.cpp
new file mode 100644
index 0000000..e119e22
--- /dev/null
+++ b/themes/LeafParticleRender.cpp
@@ -0,0 +1,51 @@
+#include "LeafParticleRender.h"
+#include "Renderer2d.h"
+
+void LeafParticleRender::load(Renderer2d *renderer, TreeShape *tree) {
+ numVertices = 0;
+ numLeaves = 0;
+
+ vertices = new Renderer2dVertex[numVertices];
+
+ useShader(renderer->shader);
+
+ glGenVertexArrays(1, &vao);
+ glBindVertexArray(vao);
+
+ glGenBuffers(1, &vbo);
+ glBindBuffer(GL_ARRAY_BUFFER, vbo);
+ glBufferData(GL_ARRAY_BUFFER, numVertices * sizeof(Renderer2dVertex), &vertices[0], GL_DYNAMIC_DRAW);
+
+ glEnableVertexAttribArray(renderer->attributes.position);
+ glVertexAttribPointer(renderer->attributes.position, 2, GL_FLOAT, GL_FALSE, sizeof(Renderer2dVertex), (GLvoid *)0);
+
+ glEnableVertexAttribArray(renderer->attributes.color);
+ glVertexAttribPointer(renderer->attributes.color, 4, GL_FLOAT, GL_FALSE, sizeof(Renderer2dVertex), (GLvoid *)offsetof(Renderer2dVertex, color));
+
+ glEnableVertexAttribArray(renderer->attributes.scale);
+ glVertexAttribPointer(renderer->attributes.scale, 2, GL_FLOAT, GL_FALSE, sizeof(Renderer2dVertex), (GLvoid *)offsetof(Renderer2dVertex, scale));
+
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glBindVertexArray(0);
+}
+
+void LeafParticleRender::update(float32 dtSeconds) {
+
+}
+
+void LeafParticleRender::render(Renderer2d *renderer) {
+ setShaderMat4(renderer->uniforms.model, model);
+
+ glBindBuffer(GL_ARRAY_BUFFER, vbo);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, numVertices * sizeof(Renderer2dVertex), &vertices[0]);
+
+ glBindVertexArray(vao);
+ glDrawArraysInstanced(GL_TRIANGLES, 0, 6 * numVertices, numLeaves);
+ glBindVertexArray(0);
+}
+
+void LeafParticleRender::unload() {
+ glDeleteVertexArrays(1, &vao);
+ glDeleteBuffers(1, &vbo);
+ delete [] vertices;
+} \ No newline at end of file
diff --git a/themes/LeafParticleRender.h b/themes/LeafParticleRender.h
new file mode 100644
index 0000000..5953000
--- /dev/null
+++ b/themes/LeafParticleRender.h
@@ -0,0 +1,35 @@
+#include "Renderer2d.h"
+#include "mathlib.h"
+#include "types.h"
+
+struct TreeShape;
+
+struct LeafParticleLoadData {
+ Vector2 initPosition;
+ Vector4 initColor;
+ int numLeaves = 48;
+};
+
+struct LeafParticleUpdateData {
+ bool canFall = false;
+ Vector4 color = Vector4(1.f, 0.f, 0.f, 0.f);
+ float32 scale = 1.f;
+ Vector2 fallDirection;
+};
+
+struct LeafParticleRender {
+ // Update data
+ int32 numLeaves = 0;
+ Renderer2dVertex* vertices = NULL;
+
+ // Render data
+ uint32 vao;
+ uint32 vbo;
+ uint32 numVertices = 0;
+ Mat4x4 model;
+
+ void load(Renderer2d* renderer, TreeShape* tree);
+ void update(float32 dtSeconds);
+ void render(Renderer2d* renderer);
+ void unload();
+}; \ No newline at end of file
diff --git a/themes/Renderer2d.cpp b/themes/Renderer2d.cpp
index 7a69ba4..44dc7df 100644
--- a/themes/Renderer2d.cpp
+++ b/themes/Renderer2d.cpp
@@ -1,15 +1,19 @@
#include "Renderer2d.h"
+#include "Shader.h"
#include "WebglContext.h"
#include "mathlib.h"
+// Note: In the 'transform' attribute, the transform.x is the scale,
+// transform.y is the rotation, and transform.zw is the translatiob.
const char* renderer2dVertexShader =
"attribute vec2 position; \n"
"attribute vec4 color; \n"
+"attribute vec4 transform; \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"
+" vec4 fragmentPosition = projection * model * vec4(position.x * transform.x, position.y * transform.x, 1, 1); \n"
" gl_Position = fragmentPosition; \n"
" VertexColor = color; \n"
"}";
@@ -21,23 +25,26 @@ const char* renderer2dFragmentShader =
"}";
void Renderer2d::load(WebglContext* context) {
- printf("Compiling orthographic shader...\n");
+ printf("Compiling Renderer2d shader...\n");
shader = loadShader(renderer2dVertexShader, renderer2dFragmentShader);
useShader(shader);
attributes.position = getShaderAttribute(shader, "position");
attributes.color = getShaderAttribute(shader, "color");
+ attributes.scale = getShaderAttribute(shader, "scale");
uniforms.projection = getShaderUniform(shader, "projection");
uniforms.model = getShaderUniform(shader, "model");
projection = Mat4x4().getOrthographicMatrix(0, context->width, 0, context->height);
- printf("Orthographic shader compiled.\n");
+ printf("Renderer2d shader compiled.\n");
}
void Renderer2d::render() {
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glDepthMask(GL_TRUE);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
glClearColor(clearColor.x, clearColor.y, clearColor.z, clearColor.w);
glClearDepth(1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
@@ -69,6 +76,9 @@ void Renderer2dShape::load(Renderer2dVertex* inVertices, uint32 inNumVertices, R
glEnableVertexAttribArray(renderer->attributes.color);
glVertexAttribPointer(renderer->attributes.color, 4, GL_FLOAT, GL_FALSE, sizeof(Renderer2dVertex), (GLvoid *)offsetof(Renderer2dVertex, color));
+ glEnableVertexAttribArray(renderer->attributes.scale);
+ glVertexAttribPointer(renderer->attributes.scale, 2, GL_FLOAT, GL_FALSE, sizeof(Renderer2dVertex), (GLvoid *)offsetof(Renderer2dVertex, scale));
+
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
diff --git a/themes/Renderer2d.h b/themes/Renderer2d.h
index ad79e70..0297102 100644
--- a/themes/Renderer2d.h
+++ b/themes/Renderer2d.h
@@ -15,6 +15,7 @@ struct Renderer2d {
struct {
int32 position;
int32 color;
+ int32 transform;
} attributes;
struct {
@@ -30,6 +31,7 @@ struct Renderer2d {
struct Renderer2dVertex {
Vector2 position;
Vector4 color;
+ Vector2 scale;
};
struct Renderer2dShape {
diff --git a/themes/TreeShape.cpp b/themes/TreeShape.cpp
new file mode 100644
index 0000000..b3d5c84
--- /dev/null
+++ b/themes/TreeShape.cpp
@@ -0,0 +1,159 @@
+#include "TreeShape.h"
+#include "mathlib.h"
+#include <cstdio>
+#include <cstdlib>
+
+
+void TreeBranchLoadData::fillVertices(Renderer2dVertex* vertices, int branchTier) {
+ bottomLeft = Vector2 { position.x - width / 2.f, position.y }.rotateAbout(rotation, position);
+ bottomRight = Vector2 { position.x + width / 2.f, position.y }.rotateAbout(rotation, position);
+ topLeft = (Vector2 { position.x - width / 2.f, position.y + height }).rotateAbout(rotation, position);
+ topRight = (Vector2 { position.x + width / 2.f, position.y + height }).rotateAbout(rotation, position);
+
+ topMidpoint = topLeft + (topRight - topLeft) / 2.f;
+
+ vertices[0] = { bottomLeft, color, Vector2(1, 1) };
+ vertices[1] = { bottomRight, color, Vector2(1, 1) };
+ vertices[2] = { topLeft, color, Vector2(1, 1) };
+ vertices[3] = { topLeft, color, Vector2(1, 1) };
+ vertices[4] = { topRight, color, Vector2(1, 1) };
+ vertices[5] = { bottomRight, color, Vector2(1, 1) };
+};
+
+inline float32 randomFloatBetween(float32 min, float32 max) {
+ float32 random = static_cast<float32>(rand()) / static_cast<float32>(RAND_MAX);
+ return (max - min) * random + min;
+}
+
+void TreeShape::load(Renderer2d* renderer) {
+ TreeLoadData ld;
+
+ numBranches = pow(ld.divisionsPerBranch, ld.numBranchLevels + 1);
+ numVertices = 6 * numBranches;
+
+ TreeBranchLoadData* generationData = new TreeBranchLoadData[numBranches];
+ updateData = new TreeBranchUpdateData[numBranches];
+ vertices = new Renderer2dVertex[numVertices];
+
+ int32 branchIndex = 0;
+ createBranch(&ld, generationData, numBranches, &branchIndex, 0, ld.trunkWidth, ld.trunkHeight, Vector2 { 400.f, 50.f }, 0, vertices);
+
+ useShader(renderer->shader);
+
+ glGenVertexArrays(1, &vao);
+ glBindVertexArray(vao);
+
+ glGenBuffers(1, &vbo);
+ glBindBuffer(GL_ARRAY_BUFFER, vbo);
+ glBufferData(GL_ARRAY_BUFFER, numVertices * sizeof(Renderer2dVertex), &vertices[0], GL_DYNAMIC_DRAW);
+
+ glEnableVertexAttribArray(renderer->attributes.position);
+ glVertexAttribPointer(renderer->attributes.position, 2, GL_FLOAT, GL_FALSE, sizeof(Renderer2dVertex), (GLvoid *)0);
+
+ glEnableVertexAttribArray(renderer->attributes.color);
+ glVertexAttribPointer(renderer->attributes.color, 4, GL_FLOAT, GL_FALSE, sizeof(Renderer2dVertex), (GLvoid *)offsetof(Renderer2dVertex, color));
+
+ glEnableVertexAttribArray(renderer->attributes.scale);
+ glVertexAttribPointer(renderer->attributes.scale, 2, GL_FLOAT, GL_FALSE, sizeof(Renderer2dVertex), (GLvoid *)offsetof(Renderer2dVertex, scale));
+
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glBindVertexArray(0);
+
+ delete [] generationData;
+}
+
+const float32 ninetyDegreeRotation = PI / 2.f;
+
+void TreeShape::createBranch(TreeLoadData* ld, TreeBranchLoadData* generationData, int32 numBranches, int32* branchIndex, int32 branchLevel, float32 width, float32 height, Vector2 position, float32 rotation, Renderer2dVertex* vertices) {
+ TreeBranchLoadData* branchLoadData = &generationData[*branchIndex];
+ branchLoadData->width = width;
+ branchLoadData->height = height;
+ branchLoadData->position = position;
+ branchLoadData->rotation = rotation;
+ branchLoadData->fillVertices(&vertices[(*branchIndex) * 6], branchLevel);
+
+ TreeBranchUpdateData* branchUpdateData = &updateData[*branchIndex];
+ branchUpdateData->tier = branchLevel;
+ branchUpdateData->randomOffset = randomFloatBetween(-1.f, 1.f);
+
+ if (branchLevel == ld->numBranchLevels) {
+ return;
+ }
+
+ for (int division = 0; division < ld->divisionsPerBranch; division++) {
+ // Weight between [0, 1]
+ float weight = static_cast<float32>(division) / static_cast<float32>(ld->divisionsPerBranch - 1);
+
+ // Normalize the weight between [-1, 1]
+ float32 normalizedWeight = (0.5f - (weight)) * 2.f;
+
+ // We want a rotation that takes the current rotation of the branch, and averages it between the two branches.
+ float32 branchRotationAmount = randomFloatBetween(PI / 8.f, PI / 3.f);
+ float32 branchRotation = branchLoadData->rotation + (normalizedWeight * branchRotationAmount);
+
+ // Since trees are taller vertically, we will find a normalized value that describes how far the direction is from
+ // being horizontal. If it is closer to 1, we will make the branch taller on average.
+ float32 verticalHeightScaler = (fabs(fabs(branchRotation) - ninetyDegreeRotation) / ninetyDegreeRotation) * 0.1;
+ float32 branchWidth = width * randomFloatBetween(ld->trunkWidthScalerMin, ld->trunkWidthScalerMax);
+ float32 branchHeight = height * randomFloatBetween(ld->trunkHeightScalerMin + verticalHeightScaler, ld->trunkHeightScalerMax + verticalHeightScaler);
+
+
+ // We want the branch to start within the previous branch, so we drop it down into it based off of the rotation.
+ Vector2 branchOffsetVertical = Vector2{ 0, branchWidth }.rotate(branchRotation);
+
+ Vector2 branchPosition = branchLoadData->topLeft + ((branchLoadData->topRight - branchLoadData->topLeft) * weight) - branchOffsetVertical; // Position of branch along the top of the parent branch
+
+ (*branchIndex)++;
+ createBranch(ld, generationData, numBranches, branchIndex, branchLevel + 1, branchWidth, branchHeight, branchPosition, branchRotation, vertices);
+ }
+}
+
+void TreeShape::update(float32 dtSeconds) {
+ timeElapsedSeconds += dtSeconds;
+
+ for (int32 bIdx = 0; bIdx < numBranches; bIdx++) {
+ TreeBranchUpdateData* branchUpdataData = &updateData[bIdx];
+
+ // Fade in simulation. We fade in based on the tier.
+ float32 animationStart = (branchUpdataData->tier * animateStaggerPerTier);
+ float32 animationEnd = animationStart + animateTimePerTier;
+
+ float32 alpha = 0.f;
+ if (timeElapsedSeconds < animationStart) {
+ alpha = 0.f;
+ }
+ else if (timeElapsedSeconds > animationEnd) {
+ alpha = 1.f;
+ }
+ else {
+ alpha = (1.f - (animationEnd - timeElapsedSeconds)) / animateTimePerTier;
+ }
+
+ int startParentIndex = bIdx * 6;
+ for (int32 sIdx = 0; sIdx < 6; sIdx++) {
+ int32 vidx = startParentIndex + sIdx;
+ vertices[vidx].color.w = alpha;
+
+ // Wind simualtion
+ vertices[vidx].position.x += ((branchUpdataData->randomOffset + branchUpdataData->tier) * 0.01f) * sinf(timeElapsedSeconds);
+ }
+ }
+}
+
+void TreeShape::render(Renderer2d* renderer) {
+ setShaderMat4(renderer->uniforms.model, model);
+
+ glBindBuffer(GL_ARRAY_BUFFER, vbo);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, numVertices * sizeof(Renderer2dVertex), &vertices[0]);
+
+ glBindVertexArray(vao);
+ glDrawArrays(GL_TRIANGLES, 0, numVertices);
+ glBindVertexArray(0);
+}
+
+void TreeShape::unload() {
+ glDeleteVertexArrays(1, &vao);
+ glDeleteBuffers(1, &vbo);
+ delete[] vertices;
+ delete [] updateData;
+}
diff --git a/themes/TreeShape.h b/themes/TreeShape.h
index a8e3eeb..d7570da 100644
--- a/themes/TreeShape.h
+++ b/themes/TreeShape.h
@@ -2,7 +2,18 @@
#include "types.h"
#include "mathlib.h"
-struct TreeBranch {
+struct TreeLoadData {
+ float32 trunkHeight = 96.f; // Height of the trunk start
+ float32 trunkWidth = 32.f; // Width of the trunk start
+ float32 trunkHeightScalerMin = 0.7f;
+ float32 trunkHeightScalerMax = 0.8f;
+ float32 trunkWidthScalerMin = 0.35f;
+ float32 trunkWidthScalerMax = 0.75f;
+ int32 divisionsPerBranch = 2; // How many branches to split into at each branch split
+ int32 numBranchLevels = 8; // How many branch levels to display
+};
+
+struct TreeBranchLoadData {
float32 width = 0.f;
float32 height = 0.f;
Vector2 position; // Center point
@@ -16,84 +27,33 @@ struct TreeBranch {
Vector2 topRight;
Vector2 topMidpoint;
- void fillVertices(Renderer2dVertex* vertices) {
- bottomLeft = Vector2 { position.x - width / 2.f, position.y }.rotateAbout(rotation, position);
- bottomRight = Vector2 { position.x + width / 2.f, position.y }.rotateAbout(rotation, position);
- topLeft = (Vector2 { position.x - width / 2.f, position.y + height }).rotateAbout(rotation, position);
- topRight = (Vector2 { position.x + width / 2.f, position.y + height }).rotateAbout(rotation, position);
-
- topMidpoint = topLeft + (topRight - topLeft) / 2.f;
+ void fillVertices(Renderer2dVertex* vertices, int branchTier);
+};
- vertices[0] = { bottomLeft, color };
- vertices[1] = { bottomRight, color };
- vertices[2] = { topLeft, color };
- vertices[3] = { topLeft, color };
- vertices[4] = { topRight, color };
- vertices[5] = { bottomRight, color };
- }
+struct TreeBranchUpdateData {
+ int32 tier = 0;
+ float32 randomOffset = 0;
};
struct TreeShape {
- Renderer2dShape shape;
-
- float32 height = 100.f; // Height of the whole tree
- float32 width = 40.f; // Width of the whole tree
- int32 divisionsPerBranch = 2; // How many branches to split into at each branch split
- int32 numBranchLevels = 8; // How many branch levels to display
- float32 animateTimeSeconds = 2.f; // How long it takes the tree to form
-
- void load(Renderer2d* renderer) {
- int32 numBranches = pow(divisionsPerBranch, numBranchLevels + 1);
- TreeBranch* branches = new TreeBranch[numBranches];
- int32 numVertices = 6 * numBranches;
- Renderer2dVertex* vertices = new Renderer2dVertex[numVertices];
- int32 branchIndex = 0;
-
- createBranch(branches, numBranches, &branchIndex, 0, width, height, Vector2 { 100.f, 50.f }, 0, vertices);
-
- shape.load(vertices, numVertices, renderer);
-
- delete[] branches;
- delete[] vertices;
- }
-
- void createBranch(TreeBranch* branchList, int32 numBranches, int32* branchIndex, int32 branchLevel, float32 width, float32 height, Vector2 position, float32 rotation, Renderer2dVertex* vertices) {
- TreeBranch* branch = &branchList[*branchIndex];
- branch->width = width;
- branch->height = height;
- branch->position = position;
- branch->rotation = rotation;
- branch->fillVertices(&vertices[(*branchIndex) * 6]);
-
- if (branchLevel == numBranchLevels) {
- return;
- }
-
- float32 branchWidth = width / divisionsPerBranch;
- float32 branchHeight = height / (0.7 * divisionsPerBranch);
- float32 branchRotationAmount = (PI / 4.f);
- Vector2 topBranchPos = branch->topMidpoint;
- for (int division = 0; division < divisionsPerBranch; division++) {
- float32 weight = static_cast<float32>(division) / static_cast<float32>(divisionsPerBranch - 1);
-
- float32 branchXPosition = topBranchPos.x - width / 2.f + weight * width;
- Vector2 branchPosition = (Vector2 { branchXPosition, topBranchPos.y });
- float32 branchRotation = branch->rotation + (weight * branchRotationAmount - branchRotationAmount / 2.f);
- (*branchIndex)++;
- createBranch(branchList, numBranches, branchIndex, branchLevel + 1, branchWidth, branchHeight, branchPosition, -branchRotation, vertices);
- }
- }
-
- void update(float32 dtSeconds) {
-
- }
-
- void render(Renderer2d* renderer) {
- shape.render(renderer);
- }
-
- void unload() {
- shape.unload();
- }
+ // Update data
+ TreeBranchUpdateData* updateData = NULL;
+ Renderer2dVertex* vertices = NULL;
+ float32 timeElapsedSeconds = 0.f;
+ float32 animateTimePerTier = 1.f;
+ float32 animateStaggerPerTier = 0.2f;
+ uint32 numBranches = 0;
+
+ // Render data
+ uint32 vao;
+ uint32 vbo;
+ uint32 numVertices = 0;
+ Mat4x4 model;
+
+ void load(Renderer2d* renderer);
+ void createBranch(TreeLoadData* ld, TreeBranchLoadData* branchList, int32 numBranches, int32* branchIndex, int32 branchLevel, float32 width, float32 height, Vector2 position, float32 rotation, Renderer2dVertex* vertices);
+ void update(float32 dtSeconds);
+ void render(Renderer2d* renderer);
+ void unload();
};
diff --git a/themes/WebglContext.cpp b/themes/WebglContext.cpp
index 5ef5388..3346280 100644
--- a/themes/WebglContext.cpp
+++ b/themes/WebglContext.cpp
@@ -8,4 +8,5 @@ EM_BOOL onScreenSizeChanged(int eventType, const EmscriptenUiEvent *uiEvent, voi
context->width = uiEvent->documentBodyClientWidth;
context->height = uiEvent->documentBodyClientHeight;
+ return true;
}
diff --git a/themes/deprecated/TreeRenderer.cpp b/themes/deprecated/TreeRenderer.cpp
new file mode 100644
index 0000000..ef1ed79
--- /dev/null
+++ b/themes/deprecated/TreeRenderer.cpp
@@ -0,0 +1,57 @@
+#include "TreeRenderer.h"
+#include "WebglContext.h"
+#include "mathlib.h"
+#include <GLES2/gl2.h>
+
+const char* TreeRendererVertexShader =
+"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.x, position.y, 1, 1); \n"
+" gl_Position = fragmentPosition; \n"
+" VertexColor = color; \n"
+"}";
+
+const char* TreeRendererFragmentShader =
+"varying lowp vec4 VertexColor; \n"
+"void main() { \n"
+" gl_FragColor = VertexColor; \n"
+"}";
+
+void TreeRenderer::load(WebglContext* context) {
+ printf("Compiling TreeRenderer shader...\n");
+ shader = loadShader(TreeRendererVertexShader, TreeRendererFragmentShader);
+
+ 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("TreeRenderer shader compiled.\n");
+}
+
+void TreeRenderer::render(float32 dtSeconds) {
+ timeElapsed += dtSeconds;
+
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_LEQUAL);
+ glDepthMask(GL_TRUE);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+ glClearColor(clearColor.x, clearColor.y, clearColor.z, clearColor.w);
+ glClearDepth(1.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+ useShader(shader);
+ setShaderMat4(uniforms.projection, projection);
+}
+
+void TreeRenderer::unload() {
+ glClearColor(0.f, 0.f, 0.f, 0.f);
+ glClear(GL_COLOR_BUFFER_BIT);
+ glDeleteProgram(shader);
+}
diff --git a/themes/deprecated/TreeRenderer.h b/themes/deprecated/TreeRenderer.h
new file mode 100644
index 0000000..8a8bf7f
--- /dev/null
+++ b/themes/deprecated/TreeRenderer.h
@@ -0,0 +1,36 @@
+#pragma once
+
+#include "WebglContext.h"
+#include "types.h"
+#include "Shader.h"
+#include "mathlib.h"
+
+struct WebglContext;
+
+struct TreeRenderer {
+ Mat4x4 projection;
+ uint32 shader;
+ Vector4 clearColor;
+
+ struct {
+ int32 position;
+ int32 color;
+ } attributes;
+
+ struct {
+ int32 projection;
+ int32 model;
+ } uniforms;
+
+ float32 timeElapsed = 0.f;
+ float32 frequency = 5.f;
+
+ void load(WebglContext* context);
+ void render(float32 dtSeconds);
+ void unload();
+};
+
+struct TreeRendererVertex {
+ Vector2 position;
+ Vector4 color;
+};
diff --git a/themes/dist/output.js b/themes/dist/output.js
index 01fdfb4..4e2bcc0 100644
--- a/themes/dist/output.js
+++ b/themes/dist/output.js
@@ -2520,6 +2520,8 @@ var ASM_CONSTS = {
GLctx.currentElementArrayBufferBinding = ibo ? (ibo.name | 0) : 0;
}
+ function _glBlendFunc(x0, x1) { GLctx['blendFunc'](x0, x1) }
+
function _glBufferData(target, size, data, usage) {
if (GL.currentContext.version >= 2) { // WebGL 2 provides new garbage-free entry points to call to WebGL. Use those always when possible.
@@ -2535,6 +2537,14 @@ var ASM_CONSTS = {
}
}
+ function _glBufferSubData(target, offset, size, data) {
+ if (GL.currentContext.version >= 2) { // WebGL 2 provides new garbage-free entry points to call to WebGL. Use those always when possible.
+ GLctx.bufferSubData(target, offset, HEAPU8, data, size);
+ return;
+ }
+ GLctx.bufferSubData(target, offset, HEAPU8.subarray(data, data+size));
+ }
+
function _glClear(x0) { GLctx['clear'](x0) }
function _glClearColor(x0, x1, x2, x3) { GLctx['clearColor'](x0, x1, x2, x3) }
@@ -2996,7 +3006,9 @@ var asmLibraryArg = {
"glAttachShader": _glAttachShader,
"glBindBuffer": _glBindBuffer,
"glBindVertexArray": _glBindVertexArray,
+ "glBlendFunc": _glBlendFunc,
"glBufferData": _glBufferData,
+ "glBufferSubData": _glBufferSubData,
"glClear": _glClear,
"glClearColor": _glClearColor,
"glClearDepth": _glClearDepth,
diff --git a/themes/dist/output.wasm b/themes/dist/output.wasm
index 0ebe595..0b00b5d 100755
--- a/themes/dist/output.wasm
+++ b/themes/dist/output.wasm
Binary files differ
diff --git a/themes/main.cpp b/themes/main.cpp
index 7e08011..c3ecad0 100644
--- a/themes/main.cpp
+++ b/themes/main.cpp
@@ -1,3 +1,4 @@
+#include "Renderer2d.h"
#include "WebglContext.h"
#include "MainLoop.h"
#include "Renderer2d.h"
diff --git a/themes/mathlib.cpp b/themes/mathlib.cpp
index 6fa4266..7efbb24 100644
--- a/themes/mathlib.cpp
+++ b/themes/mathlib.cpp
@@ -12,6 +12,13 @@
// ***************************************
// Vector2
+Vector2::Vector2() { }
+
+Vector2::Vector2(float inX, float inY) {
+ x = inX;
+ y = inY;
+}
+
Vector2 getRandomNormalVector2() {
Vector2 retval = {
static_cast<float>(rand()) / static_cast<float>(RAND_MAX),
diff --git a/themes/mathlib.h b/themes/mathlib.h
index a0515f1..99dfb62 100644
--- a/themes/mathlib.h
+++ b/themes/mathlib.h
@@ -25,6 +25,8 @@ struct Vector2 {
float x = 0;
float y = 0;
+ Vector2();
+ Vector2(float x, float y);
Vector2 operator+(Vector2 other);
Vector2& operator+=(Vector2 other);
Vector2 operator-(Vector2 other);