From 7f9cb5ce58fb1f760a437034e5b3bbf2e24da2c5 Mon Sep 17 00:00:00 2001 From: Joey Pollack Date: Mon, 29 Aug 2022 18:18:55 -0400 Subject: [PATCH] DrawEllipseFilled working --- docs/tasks/refactoring.todo | 6 +- src/renderer/renderer2D.cpp | 80 ++++++++++++++++++- src/renderer/renderer2D.h | 15 +++- src/renderer/shaders/ellipse.frag | 10 +++ src/renderer/shaders/ellipse.vert | 15 ++++ src/renderer/vertex_buffer.cpp | 26 ++++-- src/renderer/vertex_buffer.h | 2 + .../testbed/scenes/simple_render_scene.cpp | 19 +++-- .../testbed/scenes/simple_render_scene.h | 2 + 9 files changed, 154 insertions(+), 21 deletions(-) create mode 100644 src/renderer/shaders/ellipse.frag create mode 100644 src/renderer/shaders/ellipse.vert diff --git a/docs/tasks/refactoring.todo b/docs/tasks/refactoring.todo index 2a5fbb5..e2be0ab 100644 --- a/docs/tasks/refactoring.todo +++ b/docs/tasks/refactoring.todo @@ -5,7 +5,7 @@ ☐ Binary serializeable Renderer rewrite: - ☐ Add double buffer to the VertexBuffer class with a Flush method to send the verts to the gpu @high + ✔ Add double buffer to the VertexBuffer class with a Flush method to send the verts to the gpu @high @done(22-08-29 15:14) ✔ Add Draw method to the VertexBuffer class @high @done(22-08-29 15:06) ✔ Batch rendering minimally working @done(22-08-12 19:19) ✔ See if it's possible/better to move the matrix math into the shaders @high @done(22-08-15 14:23) @@ -26,7 +26,7 @@ Renderer rewrite: ☐ Elipse Shader ☐ Elipse Batch data - ☐ DrawLine @low + ✔ DrawLine @low @done(22-08-29 15:14) ✔ Line Shader @done(22-08-22 19:46) - ☐ Line Batch data + ✔ Line Batch data @done(22-08-29 15:14) \ No newline at end of file diff --git a/src/renderer/renderer2D.cpp b/src/renderer/renderer2D.cpp index 0673011..075a17d 100644 --- a/src/renderer/renderer2D.cpp +++ b/src/renderer/renderer2D.cpp @@ -279,7 +279,56 @@ namespace lunarium void Renderer2D::DrawEllipseFilled(glm::vec2 center_point, glm::vec2 radii, Color color, int resolution, float angle) { + float stride = 362.0f / resolution; + u32 idx_offset = mEllipseData.VertexBuffer->GetNumVerts(); + + mEllipseData.verts[0].pos = center_point; + mEllipseData.verts[0].color = color; + mEllipseData.indices[0] = idx_offset; + + float cur_deg = 0.0f; + int cur_idx = 0; + for (int i = 1; i <= resolution; i++, cur_deg += stride) + { + float rad = cur_deg * 3.14159f / 180.0f; + mEllipseData.verts[i].pos.x = center_point.x + (radii.x * cos(rad)); + mEllipseData.verts[i].pos.y = center_point.y + (radii.y * sin(rad)); + mEllipseData.verts[i].color = color; + + if (i == 1) + { + mEllipseData.indices[cur_idx] = idx_offset; + mEllipseData.indices[cur_idx + 1] = idx_offset + 1; + mEllipseData.indices[cur_idx + 2] = idx_offset + 2; + cur_idx += 3; + } + else if (i == resolution) + { + mEllipseData.indices[cur_idx] = idx_offset; + mEllipseData.indices[cur_idx + 1] = mEllipseData.indices[cur_idx - 1]; + mEllipseData.indices[cur_idx + 2] = idx_offset + 1; + cur_idx += 3; + } + else + { + mEllipseData.indices[cur_idx] = idx_offset; + mEllipseData.indices[cur_idx + 1] = mEllipseData.indices[cur_idx - 1]; + mEllipseData.indices[cur_idx + 2] = mEllipseData.indices[cur_idx - 1] + 1; + cur_idx += 3; + } + } + + + mEllipseData.VertexBuffer->PushVertices((void*)mEllipseData.verts, resolution + 1); + mEllipseData.VertexBuffer->PushIndices(mEllipseData.indices, cur_idx); + mEllipseData.NumEllipses++; + mEllipseData.NumVerts += resolution + 1; + mEllipseData.NumIndices += cur_idx; + + // Update render stats + mFrameStats.NumTris += cur_idx / 3; + mFrameStats.NumVerts += resolution; } void Renderer2D::DrawString(const char* string, Rectangle bounding_box, Color color, float scale, int font) @@ -318,7 +367,7 @@ namespace lunarium mQuadData.QuadShader->SetUniform(uprojview, (void*)glm::value_ptr(mpCamera->GetViewProjection())).LogIfFailed(LogCategory::GRAPHICS); - mQuadData.VertexBuffer->Bind(); + //mQuadData.VertexBuffer->Bind(); mQuadData.VertexBuffer->DrawArray(mQuadData.NumQuads * 6); @@ -365,7 +414,7 @@ namespace lunarium mLineData.Shader->SetUniform(uprojview, (void*)glm::value_ptr(mpCamera->GetViewProjection())).LogIfFailed(LogCategory::GRAPHICS); - mLineData.VertexBuffer->Bind(); + //mLineData.VertexBuffer->Bind(); //glDrawElements(GL_LINES, mLineData.NumLines * 2, GL_UNSIGNED_INT, nullptr); glLineWidth(mLineData.Thickness); @@ -379,6 +428,19 @@ namespace lunarium if (mEllipseData.NumEllipses > 0 && flush_mode & FlushMode::Ellipses > 0) { mEllipseData.MarkedForReset = true; + + mEllipseData.Shader->Use(); + Uniform uprojview; + uprojview.Type = UniformType::FMAT4; + uprojview.Location = -1; + uprojview.Name = "projview"; + + mEllipseData.Shader->SetUniform(uprojview, (void*)glm::value_ptr(mpCamera->GetViewProjection())).LogIfFailed(LogCategory::GRAPHICS); + + // mEllipseData.VertexBuffer->Bind(); + + mEllipseData.VertexBuffer->DrawArray(); + mFrameStats.DrawCalls++; } // Reset drawing data @@ -503,7 +565,14 @@ namespace lunarium "EllipseData::Vertex struct size does not match the vertex layout size! struct: %d, layout: %d", struct_size, layout_size); } - + // Shader + std::string vert_source = File::ReadTextFile("ellipse.vert"); + std::string frag_source = File::ReadTextFile("ellipse.frag"); + mEllipseData.Shader = new Shader(vert_source.c_str(), nullptr, frag_source.c_str()); + if (!mEllipseData.Shader->IsValid()) + { + return OpRes::Fail("Failed to create the ellipse shader"); + } return OpRes::OK(); } @@ -544,6 +613,11 @@ namespace lunarium // Reset Ellipse Data if (mEllipseData.MarkedForReset) { + mEllipseData.NumEllipses = 0; + mEllipseData.NumVerts = 0; + mEllipseData.NumIndices = 0; + + mEllipseData.VertexBuffer->Clear(); mEllipseData.MarkedForReset = false; } diff --git a/src/renderer/renderer2D.h b/src/renderer/renderer2D.h index c839961..6a1093a 100644 --- a/src/renderer/renderer2D.h +++ b/src/renderer/renderer2D.h @@ -53,8 +53,14 @@ namespace lunarium void DrawQuad(Rectangle quad, Color color, Texture* texture = nullptr, float angle = 0.0f, Rectangle sub_texture_area = Rectangle(-1, -1, -1, -1)); void DrawLine(glm::vec2 point_a, glm::vec2 point_b, Color color, float thickness = 1.0f, float angle = 0.0f); void DrawBox(Rectangle box, Color color, float thickness = 1.0f, float angle = 0.0f); - void DrawEllipse(glm::vec2 center_point, glm::vec2 radii, Color color, int resolution = 300, float thickness = 1.0f, float angle = 0.0f); - void DrawEllipseFilled(glm::vec2 center_point, glm::vec2 radii, Color color, int resolution = 300, float angle = 0.0f); + + /// Resolution is the number of sides the ellipse will have. + /// So small numbers can be used to make ngon shapes + void DrawEllipse(glm::vec2 center_point, glm::vec2 radii, Color color, int resolution = 50, float thickness = 1.0f, float angle = 0.0f); + + /// Resolution is the number of sides the ellipse will have. + /// So small numbers can be used to make ngon shapes + void DrawEllipseFilled(glm::vec2 center_point, glm::vec2 radii, Color color, int resolution = 50, float angle = 0.0f); void DrawString(const char* string, Rectangle bounding_box, Color color = {1.0f, 1.0f, 1.0f, 1.0f}, float scale = 1.0f, int font = -1); // DEBUG: @@ -155,6 +161,8 @@ namespace lunarium { bool MarkedForReset = false; int NumEllipses = 0; + int NumVerts = 0; + int NumIndices = 0; const int MaxVertices = 60000; const int MaxIndices = 60000; @@ -164,6 +172,9 @@ namespace lunarium glm::vec4 color; }; + Vertex verts[4096]; + u32 indices[4096]; + // Vertex* RawVertexBuffer; // int RawBufferIndex; // u32* RawIndexBuffer; diff --git a/src/renderer/shaders/ellipse.frag b/src/renderer/shaders/ellipse.frag new file mode 100644 index 0000000..d5714df --- /dev/null +++ b/src/renderer/shaders/ellipse.frag @@ -0,0 +1,10 @@ + +#version 450 core + +in vec4 o_Color; +out vec4 color; + +void main() +{ + color = o_Color; +} \ No newline at end of file diff --git a/src/renderer/shaders/ellipse.vert b/src/renderer/shaders/ellipse.vert new file mode 100644 index 0000000..f4886b6 --- /dev/null +++ b/src/renderer/shaders/ellipse.vert @@ -0,0 +1,15 @@ +// Draws ellipse with triangles + +#version 450 core +layout (location = 0) in vec2 position; // +layout (location = 1) in vec4 color; // + +out vec4 o_Color; + +uniform mat4 projview; + +void main() +{ + o_Color = color;//vec4(angle / 10.0, 0.0, 0.0, 1.0); + gl_Position = projview * vec4(position, 0.0, 1.0); +} \ No newline at end of file diff --git a/src/renderer/vertex_buffer.cpp b/src/renderer/vertex_buffer.cpp index 4dd2ff9..74c0a62 100644 --- a/src/renderer/vertex_buffer.cpp +++ b/src/renderer/vertex_buffer.cpp @@ -106,7 +106,7 @@ namespace lunarium if (mEBOSize > 0) { glGenBuffers(1, &mEBO); - mCPUIdxBuffer = new u32[mNumIndices]; + mCPUIdxBuffer = new u32[num_indices]; } @@ -145,10 +145,15 @@ namespace lunarium } mIndex = 0; - mEBOIndex = 0; + mNumVertices = 0; + - if (!mEBOIsStatic) + if (mNumIndices > 0 && !mEBOIsStatic) + { mNumIndices = 0; + mEBOIndex = 0; + + } } @@ -192,6 +197,11 @@ namespace lunarium return (mEBOIndex + data_size <= mEBOSize); } + u32 VertexBuffer::GetNumVerts() const + { + return mNumVertices; + } + bool VertexBuffer::PushVertices(const void* vertices, u32 num_verts) { if (mIsStatic) @@ -231,11 +241,11 @@ namespace lunarium if (mEBOIndex + data_size > mEBOSize) { // Indices do not fit into the buffer - //Logger::Warn(LogCategory::GRAPHICS, "Cannot push indices into buffer - not enough space left! Space left: %d, data size: %d", mEBOSize - mEBOIndex, data_size); + Logger::Warn(LogCategory::GRAPHICS, "Cannot push indices into buffer - not enough space left! Space left: %d, data size: %d", mEBOSize - mEBOIndex, data_size); return false; } - memcpy(mCPUIdxBuffer + mEBOIndex, indices, data_size); + memcpy(((u8*)mCPUIdxBuffer) + mEBOIndex, indices, data_size); // Bind(); // glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, mEBOIndex, data_size, indices); @@ -254,20 +264,21 @@ namespace lunarium void VertexBuffer::DrawArray(u32 num_elements) { - BindVBO(); if (!mIsStatic) { + BindVBO(); glBufferSubData(GL_ARRAY_BUFFER, 0, mIndex, mCPUBuffer); // mIndex also happens to be the size in bytes of the cpu buffer + UnbindVBO(); } GLenum primitive = (mPrimType == LayoutType::TRIANGLE) ? GL_TRIANGLES : GL_LINES; + Bind(); if (mNumIndices > 0) { if (!mEBOIsStatic) { - Bind(); glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, mEBOIndex, mCPUIdxBuffer); } @@ -282,7 +293,6 @@ namespace lunarium - UnbindVBO(); mIndex = 0; mEBOIndex = 0; diff --git a/src/renderer/vertex_buffer.h b/src/renderer/vertex_buffer.h index c04d3a1..6bf0d92 100644 --- a/src/renderer/vertex_buffer.h +++ b/src/renderer/vertex_buffer.h @@ -77,6 +77,8 @@ namespace lunarium bool WillFit(u32 num_vertices); bool IdxWillFit(u32 num_indices); + u32 GetNumVerts() const; + /// Returns false if the data does not fit in the buffer /// size is the size in bytes bool PushVertices(const void* vertices, u32 num_verts); diff --git a/src/run_modes/testbed/scenes/simple_render_scene.cpp b/src/run_modes/testbed/scenes/simple_render_scene.cpp index fb16eed..f96af83 100644 --- a/src/run_modes/testbed/scenes/simple_render_scene.cpp +++ b/src/run_modes/testbed/scenes/simple_render_scene.cpp @@ -27,7 +27,8 @@ namespace lunarium { SimpleRenderScene::SimpleRenderScene(uint32_t logCat) - : BaseScene(logCat), mTestMode(TestMode::Basic), mShapeMode(ShapeMode::Lines), mFrameTime(0.0), mNumFrames(0), mpTestImageLoad3(nullptr) + : BaseScene(logCat), mTestMode(TestMode::Basic), mShapeMode(ShapeMode::Lines), mFrameTime(0.0), mNumFrames(0), mpTestImageLoad3(nullptr), + mEllipseResolution(50), mEllipseRadii{ 100.0f, 100.0f } { srand((u32)time(0)); } @@ -172,6 +173,7 @@ namespace lunarium OrthographicCamera main_cam(Vec2f { 0.0f, 0.0f }, Sizef { (float)w, (float)h }); Core::GUI().NewFrame(); mTimer.Reset(); + Core::Graphics().ResetFrameStats(); Core::Graphics().BeginDraw(&main_cam); switch (mTestMode) @@ -191,7 +193,6 @@ namespace lunarium mFrameTime += mTimer.GetElapsedSeconds(); mNumFrames++; mRenderStats = Core::Graphics().GetFrameStats(); - Core::Graphics().ResetFrameStats(); //std::this_thread::sleep_for (std::chrono::seconds(2)); } @@ -267,7 +268,7 @@ namespace lunarium case ShapeMode::Ellipses: { - g.DrawEllipse(glm::vec2(300.0f, 300.0f), glm::vec2(25.0f, 45.0f), Color::Blue(), 300, true); + g.DrawEllipseFilled(glm::vec2(300.0f, 300.0f), glm::vec2(mEllipseRadii[0], mEllipseRadii[1]), Color::Blue(), mEllipseResolution); } break; } @@ -302,7 +303,7 @@ namespace lunarium ImGui::Text("FPS: %d", Core::GetInstance().GetFrameData().CurrentFPS); ImGui::Text("Frame Number: %d", mNumFrames); ImGui::EndChild(); - ImGui::BeginChild("Settings", ImVec2(ImGui::GetWindowSize().x - 15, ImGui::GetFrameHeightWithSpacing() * 4.5f), true); + ImGui::BeginChild("Settings", ImVec2(ImGui::GetWindowSize().x - 15, ImGui::GetFrameHeightWithSpacing() * 6.5f), true); ImGui::Text("Settings"); ImGui::Separator(); if (mTestMode == TestMode::Stress) @@ -329,7 +330,15 @@ namespace lunarium const char* shape_types[3] = { "Lines", "Boxes", "Ellipses" }; ImGui::Combo("Shape Type", (int*)&mShapeMode, shape_types, 3); ImGui::Separator(); - ImGui::DragInt("Number of Lines", &mNumLines); + if (mShapeMode == ShapeMode::Lines) + { + ImGui::DragInt("Number of Lines", &mNumLines); + } + else if (mShapeMode == ShapeMode::Ellipses) + { + ImGui::DragInt("Ellipse Resolution", &mEllipseResolution, 0.5f, 4); + ImGui::DragFloat2("Ellipse Radii", mEllipseRadii); + } if (ImGui::Button("Regenerate Shapes")) { GenerateLines(); diff --git a/src/run_modes/testbed/scenes/simple_render_scene.h b/src/run_modes/testbed/scenes/simple_render_scene.h index 491c88d..888a86f 100644 --- a/src/run_modes/testbed/scenes/simple_render_scene.h +++ b/src/run_modes/testbed/scenes/simple_render_scene.h @@ -60,6 +60,8 @@ namespace lunarium FrameBuffer* mFrameBufferTwo; float angle; float box_angle; + int mEllipseResolution; + float mEllipseRadii[2]; float mSrcWidth; float mSrcHeight;