From d781d5a3c1ec6872361db2a15786dfc0db9780f3 Mon Sep 17 00:00:00 2001 From: Matthew Kosarek Date: Tue, 5 Oct 2021 06:35:09 -0400 Subject: Working tree render, now just have to do the leaves --- themes/LeafParticleRender.cpp | 51 ++++++++++++ themes/LeafParticleRender.h | 35 ++++++++ themes/Renderer2d.cpp | 16 +++- themes/Renderer2d.h | 2 + themes/TreeShape.cpp | 159 +++++++++++++++++++++++++++++++++++++ themes/TreeShape.h | 112 +++++++++----------------- themes/WebglContext.cpp | 1 + themes/deprecated/TreeRenderer.cpp | 57 +++++++++++++ themes/deprecated/TreeRenderer.h | 36 +++++++++ themes/dist/output.js | 12 +++ themes/dist/output.wasm | Bin 44887 -> 48362 bytes themes/main.cpp | 1 + themes/mathlib.cpp | 7 ++ themes/mathlib.h | 2 + 14 files changed, 412 insertions(+), 79 deletions(-) create mode 100644 themes/LeafParticleRender.cpp create mode 100644 themes/LeafParticleRender.h create mode 100644 themes/TreeShape.cpp create mode 100644 themes/deprecated/TreeRenderer.cpp create mode 100644 themes/deprecated/TreeRenderer.h (limited to 'themes') 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 +#include + + +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(rand()) / static_cast(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(division) / static_cast(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(division) / static_cast(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 + +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 Binary files a/themes/dist/output.wasm and b/themes/dist/output.wasm 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(rand()) / static_cast(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); -- cgit v1.2.1