From f6fe40e125a99bd3ea47c476f6a95b6e820a51aa Mon Sep 17 00:00:00 2001 From: Matthew Kosarek Date: Wed, 13 Oct 2021 07:29:09 -0400 Subject: Adding square leaves to the tree --- themes/LeafParticleRender.cpp | 48 ++++++++++++++++++++----- themes/LeafParticleRender.h | 8 +++-- themes/Renderer2d.cpp | 7 +--- themes/Renderer2d.h | 2 -- themes/TreeShape.cpp | 79 ++++++++++++++++++++++++++++-------------- themes/TreeShape.h | 15 ++++++-- themes/dist/output.wasm | Bin 49375 -> 54718 bytes themes/main.cpp | 8 ++++- themes/mathlib.cpp | 1 - themes/mathlib.h | 10 ++++++ 10 files changed, 130 insertions(+), 48 deletions(-) (limited to 'themes') diff --git a/themes/LeafParticleRender.cpp b/themes/LeafParticleRender.cpp index 1abdd49..df2a453 100644 --- a/themes/LeafParticleRender.cpp +++ b/themes/LeafParticleRender.cpp @@ -1,12 +1,43 @@ #include "LeafParticleRender.h" #include "Renderer2d.h" +#include "mathlib.h" +#include "TreeShape.h" +#include "types.h" -void LeafParticleRender::load(Renderer2d *renderer, TreeShape *tree) { - numVertices = 0; - numLeaves = 0; +const int32 verticesPerLeaf = 6; +const float32 leafRadius = 3.f; +inline void createLeaf(Renderer2dVertex* vertices, Vector2 position, Vector4 color) { + Vector2 bottomLeft = Vector2(-leafRadius, -leafRadius) + position; + Vector2 bottomRight = Vector2(leafRadius, -leafRadius) + position; + Vector2 topLeft = Vector2(-leafRadius, leafRadius) + position; + Vector2 topRight = Vector2(leafRadius, leafRadius) + position; + + vertices[0] = { bottomLeft, color }; + vertices[1] = { bottomRight, color }; + vertices[2] = { topLeft, color }; + vertices[3] = { topLeft, color }; + vertices[4] = { topRight, color }; + vertices[5] = { bottomRight, color }; +} + +void LeafParticleRender::load(Renderer2d *renderer, TreeShapeLoadResult* lr) { + LeafParticleLoadData ld; + ld.numLeaves = 640; + numLeaves = ld.numLeaves; + numVertices = ld.numLeaves * verticesPerLeaf; + + updateData = new LeafParticleUpdateData[numLeaves]; vertices = new Renderer2dVertex[numVertices]; + for (int32 leafIdx = 0; leafIdx < numLeaves; leafIdx++) { + int32 randomBranch = randomIntBetween(0, lr->numBranches); + int32 randomVertex = randomIntBetween(0, 6); // TODO: Manually entering num vertices per branch. + updateData[leafIdx].vertexToFollow = &lr->updateData[randomBranch].vertices[randomVertex]; + updateData[leafIdx].color = Vector4(randomFloatBetween(0.3, 0.9), randomFloatBetween(0.1, 0.6), 0, 1); + updateData[leafIdx].vertexPtr = &vertices[leafIdx * verticesPerLeaf]; + } + useShader(renderer->shader); glGenVertexArrays(1, &vao); @@ -22,15 +53,16 @@ void LeafParticleRender::load(Renderer2d *renderer, TreeShape *tree) { glEnableVertexAttribArray(renderer->attributes.color); glVertexAttribPointer(renderer->attributes.color, 4, GL_FLOAT, GL_FALSE, sizeof(Renderer2dVertex), (GLvoid *)offsetof(Renderer2dVertex, color)); - glEnableVertexAttribArray(renderer->attributes.transform); - glVertexAttribPointer(renderer->attributes.transform, 4, GL_FLOAT, GL_FALSE, sizeof(Renderer2dVertex), (GLvoid *)offsetof(Renderer2dVertex, transform)); - glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); } void LeafParticleRender::update(float32 dtSeconds) { - + for (int32 leafIdx = 0; leafIdx < numLeaves; leafIdx++) { + auto updateDataItem = &updateData[leafIdx]; + + createLeaf(updateDataItem->vertexPtr, updateDataItem->vertexToFollow->position, updateDataItem->color); + } } void LeafParticleRender::render(Renderer2d *renderer) { @@ -40,7 +72,7 @@ void LeafParticleRender::render(Renderer2d *renderer) { glBufferSubData(GL_ARRAY_BUFFER, 0, numVertices * sizeof(Renderer2dVertex), &vertices[0]); glBindVertexArray(vao); - glDrawArraysInstanced(GL_TRIANGLES, 0, 6 * numVertices, numLeaves); + glDrawArrays(GL_TRIANGLES, 0, numVertices); glBindVertexArray(0); } diff --git a/themes/LeafParticleRender.h b/themes/LeafParticleRender.h index 5953000..c305363 100644 --- a/themes/LeafParticleRender.h +++ b/themes/LeafParticleRender.h @@ -2,7 +2,7 @@ #include "mathlib.h" #include "types.h" -struct TreeShape; +struct TreeShapeLoadResult; struct LeafParticleLoadData { Vector2 initPosition; @@ -12,14 +12,18 @@ struct LeafParticleLoadData { struct LeafParticleUpdateData { bool canFall = false; + Renderer2dVertex* vertexToFollow = NULL; Vector4 color = Vector4(1.f, 0.f, 0.f, 0.f); float32 scale = 1.f; Vector2 fallDirection; + Renderer2dVertex* vertexPtr = NULL; }; struct LeafParticleRender { // Update data int32 numLeaves = 0; + + LeafParticleUpdateData* updateData = NULL; Renderer2dVertex* vertices = NULL; // Render data @@ -28,7 +32,7 @@ struct LeafParticleRender { uint32 numVertices = 0; Mat4x4 model; - void load(Renderer2d* renderer, TreeShape* tree); + void load(Renderer2d* renderer, TreeShapeLoadResult* lr); void update(float32 dtSeconds); void render(Renderer2d* renderer); void unload(); diff --git a/themes/Renderer2d.cpp b/themes/Renderer2d.cpp index 3e29656..2750557 100644 --- a/themes/Renderer2d.cpp +++ b/themes/Renderer2d.cpp @@ -9,12 +9,11 @@ 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.x + transform.x, position.y + transform.x, 1, 1); \n" +" vec4 fragmentPosition = projection * model * vec4(position.x, position.y, 0, 1); \n" " gl_Position = fragmentPosition; \n" " VertexColor = color; \n" "}"; @@ -46,7 +45,6 @@ void Renderer2d::load(WebglContext* inContext) { useShader(shader); attributes.position = getShaderAttribute(shader, "position"); attributes.color = getShaderAttribute(shader, "color"); - attributes.transform = getShaderAttribute(shader, "transform"); uniforms.projection = getShaderUniform(shader, "projection"); uniforms.model = getShaderUniform(shader, "model"); projection = Mat4x4().getOrthographicMatrix(0, context->width, 0, context->height); @@ -93,9 +91,6 @@ 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.transform); - glVertexAttribPointer(renderer->attributes.transform, 2, GL_FLOAT, GL_FALSE, sizeof(Renderer2dVertex), (GLvoid *)offsetof(Renderer2dVertex, transform)); - glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); } diff --git a/themes/Renderer2d.h b/themes/Renderer2d.h index 33e0dac..cbdf4d4 100644 --- a/themes/Renderer2d.h +++ b/themes/Renderer2d.h @@ -16,7 +16,6 @@ struct Renderer2d { struct { int32 position; int32 color; - int32 transform; } attributes; struct { @@ -32,7 +31,6 @@ struct Renderer2d { struct Renderer2dVertex { Vector2 position; Vector4 color; - Vector4 transform; }; struct Renderer2dShape { diff --git a/themes/TreeShape.cpp b/themes/TreeShape.cpp index ec9e052..8532fdc 100644 --- a/themes/TreeShape.cpp +++ b/themes/TreeShape.cpp @@ -2,7 +2,7 @@ #include "mathlib.h" #include #include - +#include void TreeBranchLoadData::fillVertices(Renderer2dVertex* vertices, int branchTier) { bottomLeft = Vector2 { position.x - width / 2.f, position.y }.rotateAbout(rotation, position); @@ -12,20 +12,17 @@ void TreeBranchLoadData::fillVertices(Renderer2dVertex* vertices, int branchTier topMidpoint = topLeft + (topRight - topLeft) / 2.f; - vertices[0] = { bottomLeft, color, Vector4(0, 0, 0, 0) }; - vertices[1] = { bottomRight, color, Vector4(0, 0, 0, 0) }; - vertices[2] = { topLeft, color, Vector4(0, 0, 0, 0) }; - vertices[3] = { topLeft, color, Vector4(0, 0, 0, 0) }; - vertices[4] = { topRight, color, Vector4(0, 0, 0, 0) }; - vertices[5] = { bottomRight, color, Vector4(0, 0, 0, 0) }; + vertices[0] = { bottomLeft, color}; + vertices[1] = { bottomRight, color}; + vertices[2] = { topLeft, color}; + vertices[3] = { topLeft, color}; + vertices[4] = { topRight, color}; + vertices[5] = { bottomRight, color}; }; -inline float32 randomFloatBetween(float32 min, float32 max) { - float32 random = static_cast(rand()) / static_cast(RAND_MAX); - return (max - min) * random + min; -} +TreeShapeLoadResult TreeShape::load(Renderer2d* renderer) { + timeElapsedSeconds = 0; -void TreeShape::load(Renderer2d* renderer) { TreeLoadData ld; numBranches = pow(ld.divisionsPerBranch, ld.numBranchLevels + 1); @@ -35,8 +32,14 @@ void TreeShape::load(Renderer2d* renderer) { updateData = new TreeBranchUpdateData[numBranches]; vertices = new Renderer2dVertex[numVertices]; + // The load result will contain information that we can pass on to our leaf renderer. + TreeShapeLoadResult lr; + lr.lowerBounds = Vector2(FLT_MAX, FLT_MAX); + lr.upperBounds = Vector2(FLT_MIN, FLT_MIN); + lr.updateData = updateData; + lr.numBranches = numBranches; int32 branchIndex = 0; - createBranch(&ld, generationData, numBranches, &branchIndex, 0, ld.trunkWidth, ld.trunkHeight, Vector2 { 400.f, 50.f }, 0, vertices); + createBranch(&ld, generationData, numBranches, &branchIndex, 0, ld.trunkWidth, ld.trunkHeight, Vector2 { 300.f, 50.f }, 0, vertices, &lr); useShader(renderer->shader); @@ -53,18 +56,17 @@ void TreeShape::load(Renderer2d* renderer) { glEnableVertexAttribArray(renderer->attributes.color); glVertexAttribPointer(renderer->attributes.color, 4, GL_FLOAT, GL_FALSE, sizeof(Renderer2dVertex), (GLvoid *)offsetof(Renderer2dVertex, color)); - glEnableVertexAttribArray(renderer->attributes.transform); - glVertexAttribPointer(renderer->attributes.transform, 4, GL_FLOAT, GL_FALSE, sizeof(Renderer2dVertex), (GLvoid *)offsetof(Renderer2dVertex, transform)); - glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); delete [] generationData; + + return lr; } 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) { +void TreeShape::createBranch(TreeLoadData* ld, TreeBranchLoadData* generationData, int32 numBranches, int32* branchIndex, int32 branchLevel, float32 width, float32 height, Vector2 position, float32 rotation, Renderer2dVertex* vertices, TreeShapeLoadResult* lr) { TreeBranchLoadData* branchLoadData = &generationData[*branchIndex]; branchLoadData->width = width; branchLoadData->height = height; @@ -72,9 +74,24 @@ void TreeShape::createBranch(TreeLoadData* ld, TreeBranchLoadData* generationDat branchLoadData->rotation = rotation; branchLoadData->fillVertices(&vertices[(*branchIndex) * 6], branchLevel); + // Fil in the bounds for the LeafRenderer later. + if (branchLoadData->topMidpoint.x > lr->upperBounds.x) { + lr->upperBounds.x = branchLoadData->topMidpoint.x; + } + if (branchLoadData->topMidpoint.y > lr->upperBounds.y) { + lr->upperBounds.y = branchLoadData->topMidpoint.y; + } + if (branchLoadData->topMidpoint.x < lr->lowerBounds.x) { + lr->lowerBounds.x = branchLoadData->topMidpoint.x; + } + if (branchLoadData->topMidpoint.y < lr->lowerBounds.y) { + lr->lowerBounds.y = branchLoadData->topMidpoint.y; + } + TreeBranchUpdateData* branchUpdateData = &updateData[*branchIndex]; branchUpdateData->tier = branchLevel; branchUpdateData->randomOffset = randomFloatBetween(-1.f, 1.f); + branchUpdateData->vertices = &vertices[(*branchIndex) * 6]; if (branchLevel == ld->numBranchLevels) { return; @@ -104,7 +121,7 @@ void TreeShape::createBranch(TreeLoadData* ld, TreeBranchLoadData* generationDat 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); + createBranch(ld, generationData, numBranches, branchIndex, branchLevel + 1, branchWidth, branchHeight, branchPosition, branchRotation, vertices, lr); } } @@ -129,14 +146,21 @@ void TreeShape::update(float32 dtSeconds) { 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); - } + int32 startParentIndex = bIdx * 6; + float32 xOffset = ((branchUpdataData->randomOffset + branchUpdataData->tier) * 0.01f) * sinf(timeElapsedSeconds); + + branchUpdataData->vertices[0].color.w = alpha; + branchUpdataData->vertices[0].position.x += xOffset; + branchUpdataData->vertices[1].color.w = alpha; + branchUpdataData->vertices[1].position.x += xOffset; + branchUpdataData->vertices[2].color.w = alpha; + branchUpdataData->vertices[2].position.x += xOffset; + branchUpdataData->vertices[3].color.w = alpha; + branchUpdataData->vertices[3].position.x += xOffset; + branchUpdataData->vertices[4].color.w = alpha; + branchUpdataData->vertices[4].position.x += xOffset; + branchUpdataData->vertices[5].color.w = alpha; + branchUpdataData->vertices[5].position.x += xOffset; } } @@ -156,4 +180,7 @@ void TreeShape::unload() { glDeleteBuffers(1, &vbo); delete[] vertices; delete [] updateData; + timeElapsedSeconds = 0; + vertices = NULL; + updateData = NULL; } diff --git a/themes/TreeShape.h b/themes/TreeShape.h index d7570da..06a8f81 100644 --- a/themes/TreeShape.h +++ b/themes/TreeShape.h @@ -33,6 +33,15 @@ struct TreeBranchLoadData { struct TreeBranchUpdateData { int32 tier = 0; float32 randomOffset = 0; + Renderer2dVertex* vertices = NULL; +}; + +struct TreeShapeLoadResult { + Vector2 lowerBounds; + Vector2 upperBounds; + Vector2 center; + TreeBranchUpdateData* updateData; + uint32 numBranches = 0; }; struct TreeShape { @@ -50,8 +59,10 @@ struct TreeShape { 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); + TreeShapeLoadResult 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, TreeShapeLoadResult* lr); void update(float32 dtSeconds); void render(Renderer2d* renderer); void unload(); diff --git a/themes/dist/output.wasm b/themes/dist/output.wasm index 17a1d97..32331e3 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 c3ecad0..e037dcf 100644 --- a/themes/main.cpp +++ b/themes/main.cpp @@ -4,6 +4,7 @@ #include "Renderer2d.h" #include "types.h" #include "TreeShape.h" +#include "LeafParticleRender.h" enum Theme { Default = 0, @@ -12,6 +13,7 @@ enum Theme { struct AutumnTheme { TreeShape tree; + LeafParticleRender leafParticles; void load(Renderer2d* renderer); void update(float32 dtSeconds); @@ -114,18 +116,22 @@ EM_BOOL selectAutumn(int eventType, const EmscriptenMouseEvent* mouseEvent, void // -- Autumn theme3 void AutumnTheme::load(Renderer2d* renderer) { renderer->clearColor = Vector4(252,76,2, 0.5).toNormalizedColor(); - tree.load(renderer); + auto lr = tree.load(renderer); + leafParticles.load(renderer, &lr); } void AutumnTheme::update(float32 dtSeconds) { tree.update(dtSeconds); + leafParticles.update(dtSeconds); } void AutumnTheme::render(Renderer2d* renderer) { tree.render(renderer); + leafParticles.render(renderer); } void AutumnTheme::unload() { tree.unload(); + leafParticles.unload(); } diff --git a/themes/mathlib.cpp b/themes/mathlib.cpp index 7efbb24..ee9bb1d 100644 --- a/themes/mathlib.cpp +++ b/themes/mathlib.cpp @@ -348,7 +348,6 @@ void Vector4::printDebug(const char* name) { printf("%s=Vector4(%f, %f, %f, %f)\n", name, x, y, z, w); } - // *************************************** // Mat4x4 Mat4x4 Mat4x4::copy() { diff --git a/themes/mathlib.h b/themes/mathlib.h index 99dfb62..82f85a2 100644 --- a/themes/mathlib.h +++ b/themes/mathlib.h @@ -21,6 +21,16 @@ #define DEG_TO_RAD(x) (x * (PI / 180.f)) #define RAD_TO_DEG(x) (x * (180.f / PI)) +// -- Random +inline float randomFloatBetween(float min, float max) { + float random = static_cast(rand()) / static_cast(RAND_MAX); + return (max - min) * random + min; +} + +inline int randomIntBetween(int min, int max) { + return static_cast(randomFloatBetween(min, max)); +} + struct Vector2 { float x = 0; float y = 0; -- cgit v1.2.1