diff --git a/docs/tasks/refactoring.todo b/docs/tasks/refactoring.todo index 5cd3939..94f48cc 100644 --- a/docs/tasks/refactoring.todo +++ b/docs/tasks/refactoring.todo @@ -5,6 +5,7 @@ ☐ Binary serializeable Renderer rewrite: + ☐ Add Draw method to the VertexBuffer class @high ✔ 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) ✔ Textures in batch renderer @high @done(22-08-18 16:09) diff --git a/src/renderer/renderer2D.cpp b/src/renderer/renderer2D.cpp index c43e29e..6558e67 100644 --- a/src/renderer/renderer2D.cpp +++ b/src/renderer/renderer2D.cpp @@ -143,7 +143,7 @@ namespace lunarium if (mQuadData.RawBufferIndex + 4 > mQuadData.MaxVertices) { - Flush(); + Flush(FlushMode::Quads); } float tex_is_grey_scale = (texture && texture->GetFormat() == TextureFormat::RED) ? 1.0f : 0.0f; @@ -222,6 +222,48 @@ namespace lunarium } + void Renderer2D::DrawLine(glm::vec2 point_a, glm::vec2 point_b, Color color, float thickness, float angle) + { + if (thickness != mLineData.Thickness || mLineData.RawBufferIndex + 2 > mLineData.MaxVertices) + { + Flush(FlushMode::Lines); + mLineData.Thickness = thickness; + } + + glm::mat4 model = glm::mat4(1.0f); + glm::rotate(model, angle, glm::vec3(0.0f, 0.0f, 1.0f)); + + // V1 + LineData::Vertex v1; + int vert_size = sizeof(LineData::Vertex); + //glm::vec4 long_pos = glm::vec4(point_a.x, point_a.y, 0.0f, 1.0f) * model; + v1.pos = point_a;//glm::vec2(long_pos.x, long_pos.y); + v1.color = color; + memcpy(&mLineData.RawVertexBuffer[mLineData.RawBufferIndex], &v1, vert_size); + mLineData.RawBufferIndex += 1; + + // V2 + LineData::Vertex v2; + //long_pos = glm::vec4(point_b.x, point_b.y, 0.0f, 1.0f) * model; + v2.pos = point_b;//glm::vec2(long_pos.x, long_pos.y); + v2.color = color; + memcpy(&mLineData.RawVertexBuffer[mLineData.RawBufferIndex], &v2, vert_size); + mLineData.RawBufferIndex += 1; + + mLineData.NumLines++; + mFrameStats.NumVerts += 2; + } + + void Renderer2D::DrawBox(Rectangle box, Color color, float thickness, float angle) + { + Logger::Warn(LogCategory::GRAPHICS, "Renderer2D::DrawBox is not implemented yet"); + } + + void Renderer2D::DrawEllipse(glm::vec2 center_point, glm::vec2 radii, Color color, bool filled, float thickness, float angle) + { + Logger::Warn(LogCategory::GRAPHICS, "Renderer2D::DrawEllipse is not implemented yet"); + } + void Renderer2D::DrawString(const char* string, Rectangle bounding_box, Color color, float scale, int font) { u32 f = font < 0 ? mDefaultFont : font; @@ -235,7 +277,7 @@ namespace lunarium void Renderer2D::Flush(int flush_mode) { // Draw quads - if (mQuadData.NumQuads > 0 && flush_mode & (1 << FlushMode::Quads) > 0) + if (mQuadData.NumQuads > 0 && flush_mode & FlushMode::Quads > 0) { mQuadData.MarkedForReset = true; if (!mQuadData.VertexBuffer->PushVertices(mQuadData.RawVertexBuffer, mQuadData.NumQuads * 4)) @@ -262,9 +304,9 @@ namespace lunarium glDrawElements(GL_TRIANGLES, mQuadData.NumQuads * 6, GL_UNSIGNED_INT, nullptr); - mQuadData.WireFrameShader->Use(); - uprojview.Location = -1; - mQuadData.WireFrameShader->SetUniform(uprojview, (void*)glm::value_ptr(mpCamera->GetViewProjection())).LogIfFailed(LogCategory::GRAPHICS); + // mQuadData.WireFrameShader->Use(); + // uprojview.Location = -1; + // mQuadData.WireFrameShader->SetUniform(uprojview, (void*)glm::value_ptr(mpCamera->GetViewProjection())).LogIfFailed(LogCategory::GRAPHICS); // Uniform ucolor; // ucolor.Type = UniformType::F4; @@ -281,13 +323,36 @@ namespace lunarium } // Draw Lines - if (mLineData.NumLines > 0 && flush_mode & (1 << FlushMode::Lines) > 0) + int draw = flush_mode & FlushMode::Lines; + if (mLineData.NumLines > 0 && draw > 0) { mLineData.MarkedForReset = true; + if (!mLineData.VertexBuffer->PushVertices(mLineData.RawVertexBuffer, mLineData.NumLines * 2)) + { + Logger::Error(LogCategory::GRAPHICS, "Could not push verts into the line buffer!"); + ResetDrawingData(); + return; + } + + mLineData.Shader->Use(); + Uniform uprojview; + uprojview.Type = UniformType::FMAT4; + uprojview.Location = -1; + uprojview.Name = "projview"; + + mLineData.Shader->SetUniform(uprojview, (void*)glm::value_ptr(mpCamera->GetViewProjection())).LogIfFailed(LogCategory::GRAPHICS); + + mLineData.VertexBuffer->Bind(); + + //glDrawElements(GL_LINES, mLineData.NumLines * 2, GL_UNSIGNED_INT, nullptr); + glLineWidth(mLineData.Thickness); + glDrawArrays(GL_LINES, 0, mLineData.NumLines * 2); + mFrameStats.DrawCalls++; + } // Draw Ellipses - if (mEllipseData.NumEllipses > 0 && flush_mode & (1 << FlushMode::Ellipses) > 0) + if (mEllipseData.NumEllipses > 0 && flush_mode & FlushMode::Ellipses > 0) { mEllipseData.MarkedForReset = true; } @@ -367,6 +432,28 @@ namespace lunarium OpRes Renderer2D::InitLineData() { + mLineData.BufferLayout.PushVertexAttribute(VertexAttribute { VertexAttributeType::FLOAT32, 2 }); // Position + mLineData.BufferLayout.PushVertexAttribute(VertexAttribute { VertexAttributeType::FLOAT32, 4 }); // Color + mLineData.VertexBuffer = VertexBuffer::Create(mLineData.BufferLayout, mLineData.MaxVertices); + + mLineData.RawVertexBuffer = new LineData::Vertex[mLineData.MaxVertices]; + mLineData.RawBufferIndex = 0; + + int layout_size = mLineData.BufferLayout.GetLayoutSizeInBytes(); + int struct_size = sizeof(LineData::Vertex); + if (struct_size != layout_size) + { + Logger::Error(LogCategory::GRAPHICS, + "LineData::Vertex struct size does not match the vertex layout size! struct: %d, layout: %d", struct_size, layout_size); + } + + std::string vert_source = File::ReadTextFile("line.vert"); + std::string frag_source = File::ReadTextFile("line.frag"); + mLineData.Shader = new Shader(vert_source.c_str(), nullptr, frag_source.c_str()); + if (!mLineData.Shader->IsValid()) + { + return OpRes::Fail("Failed to create the line shader"); + } return OpRes::OK(); } @@ -403,6 +490,10 @@ namespace lunarium // Reset Line Data if (mLineData.MarkedForReset) { + mLineData.VertexBuffer->Clear(); + mLineData.NumLines = 0; + mLineData.RawBufferIndex = 0; + mLineData.Thickness = 1.0f; mLineData.MarkedForReset = false; } diff --git a/src/renderer/renderer2D.h b/src/renderer/renderer2D.h index ac96c51..60bdd5a 100644 --- a/src/renderer/renderer2D.h +++ b/src/renderer/renderer2D.h @@ -154,6 +154,20 @@ namespace lunarium { bool MarkedForReset = false; int NumEllipses = 0; + const int MaxVertices = 60000; + + struct Vertex + { + glm::vec2 pos; + glm::vec4 color; + }; + + Vertex* RawVertexBuffer; + int RawBufferIndex; + + BufferLayout BufferLayout; + VertexBuffer* VertexBuffer; + Shader* Shader; } mEllipseData; @@ -175,12 +189,12 @@ namespace lunarium glm::vec4 color; }; - Vertex* mRawVertexBuffer; - int mRawBufferIndex; + Vertex* RawVertexBuffer; + int RawBufferIndex; - BufferLayout mBufferLayout; - VertexBuffer* mVertexBuffer; - Shader* mShader; + BufferLayout BufferLayout; + VertexBuffer* VertexBuffer; + Shader* Shader; } mLineData; diff --git a/src/renderer/shaders/line.frag b/src/renderer/shaders/line.frag index cbbd6b4..d5714df 100644 --- a/src/renderer/shaders/line.frag +++ b/src/renderer/shaders/line.frag @@ -1,5 +1,6 @@ #version 450 core + in vec4 o_Color; out vec4 color; diff --git a/src/renderer/shaders/line.vert b/src/renderer/shaders/line.vert index c260f68..33e54b2 100644 --- a/src/renderer/shaders/line.vert +++ b/src/renderer/shaders/line.vert @@ -5,8 +5,10 @@ layout (location = 1) in vec4 color; // out vec4 o_Color; +uniform mat4 projview; + void main() { o_Color = color; - gl_Position = vec4(vertex, 0.0, 1.0); + gl_Position = projview * vec4(position, 0.0, 1.0); } \ No newline at end of file diff --git a/src/run_modes/testbed/scenes/simple_render_scene.cpp b/src/run_modes/testbed/scenes/simple_render_scene.cpp index e541999..8dc2a7f 100644 --- a/src/run_modes/testbed/scenes/simple_render_scene.cpp +++ b/src/run_modes/testbed/scenes/simple_render_scene.cpp @@ -52,75 +52,10 @@ namespace lunarium mFrameBufferTwo = FrameBuffer::Create(1024, 1024); //Core::Graphics().CreateRenderTexture(1024, 1024, 4); // Load test image - int w, h, n; - stbi_set_flip_vertically_on_load(0); - unsigned char* buffer = stbi_load("LinkToThePast1_sized.png", &w, &h, &n, 0); - - TextureFormat format = TextureFormat::RGBA; - if (n == 3) - { - format = TextureFormat::RGB; - } - mpTestImageLoad = Texture::Create(buffer, w, h, format, true); - mSrcWidth = w; - mSrcHeight = h; - - delete[] buffer; - stbi_set_flip_vertically_on_load(0); - buffer = stbi_load("debug_texture.jpeg", &w, &h, &n, 0); - //buffer = stbi_load("lunarium_text_test.png", &w, &h, &n, 0); - - format = TextureFormat::RGBA; - if (n == 3) - { - format = TextureFormat::RGB; - } - else if (n == 1) - { - format = TextureFormat::RED; - } - - mpTestImageLoad2 = Texture::Create(buffer, w, h, format); - delete[] buffer; - - stbi_set_flip_vertically_on_load(0); - buffer = stbi_load("lunarium_text_test.png", &w, &h, &n, 0); - - format = TextureFormat::RGBA; - if (n == 3) - { - format = TextureFormat::RGB; - } - else if (n == 1) - { - format = TextureFormat::RED; - } - - mpTestImageLoad3 = Texture::Create(buffer, w, h, format); - delete[] buffer; + LoadImages(); - mQuads = new Rectangle[NUM_QUADS]; - for (int i = 0; i < NUM_QUADS; i++) - { - float x = (rand() % 1000); - float y = (rand() % 600); - float w = (rand() % 200) + 10; - float h = (rand() % 200) + 10; - - mQuads[i] = Rectangle(x, y, w, h); - } - - mQuadColors = new Color[NUM_QUADS]; - mQuadTexures = new Texture*[NUM_QUADS]; - - for (int i = 0; i < NUM_QUADS; i++) - { - mQuadTexures[i] = (i % 2 == 0) ? mpTestImageLoad : mpTestImageLoad2; - mQuadColors[i].R = ((float)(rand() % 10000)) / 10000.0f; - mQuadColors[i].G = ((float)(rand() % 10000)) / 10000.0f; - mQuadColors[i].B = ((float)(rand() % 10000)) / 10000.0f; - mQuadColors[i].A = 1.0f; - } + GenerateQuads(); + GenerateLines(); angle = 0.0f; box_angle = 0.0f; @@ -192,56 +127,9 @@ namespace lunarium angle -= 0.1f; } - if (Core::Input().IsKeyPressed(KeyCode::TAB)) - { - if (mTestMode == TestMode::Basic) - mTestMode = TestMode::Stress; - - else if (mTestMode == TestMode::Stress) - { - mSubTex = Rectangle::MakeFromTopLeft(2858, 0, 32, 32); - mTestMode = TestMode::String; - } - - else if (mTestMode == TestMode::String) - { - mTestMode = TestMode::Basic; - mSubTex = Rectangle::MakeFromTopLeft(0, 0, 256, 256); - } - } - if (Core::Input().IsKeyPressed(KeyCode::Q)) { - // Test writing out a rendered image with transparency - Renderer2D& g = Core::Graphics(); - Color prev = g.GetClearColor(); - g.SetClearColor(Color(0.0f, 0.0f, 0.0f, 0.0f)); - mFrameBufferTwo->Bind(); - OrthographicCamera cam(Vec2f{0.0f, 0.0f}, Sizef{(float)mFrameBufferTwo->GetTexture()->GetWidth(), (float)mFrameBufferTwo->GetTexture()->GetHeight()}); - g.BeginDraw(&cam); - // if (Failed(result)) - // { - // Logger::Warn(mLogCat, "Unable to render to texture: %s", result.Description.c_str()); - // return; - // } - - Logger::Info(mLogCat, "Running transparent image test"); - - g.DrawQuad(Rectangle(500, 400, 300, 300), Color(0.5f, 0.0f, 0.75f, 1.0f)); - g.DrawQuad(Rectangle(200, 300, 100, 100), Color(0.2f, 0.5f, 0.4f, 1.0f), nullptr, 45.0f); - g.DrawString("This is a test of rendering an image with transparency", - Rectangle::MakeFromTopLeft(50, 50, 600, 200), Color(0.0f, 1.0f, 0.2f, 1.0f), 0.5f); - - g.EndDraw(); - mpRenderedImage = mFrameBufferTwo->GetTexture(); - mFrameBufferTwo->Unbind(); - //mpRenderedImage = Core::GetInstance().EndRenderToTexture(); - g.SetClearColor(prev); - - stbi_flip_vertically_on_write(1); - stbi_write_png("lunarium_test_image.png", mpRenderedImage->GetWidth(), mpRenderedImage->GetHeight(), 4, - mpRenderedImage->GetPixels(), mpRenderedImage->GetWidth() * 4); - //Logger::Info(mLogCat, "") + DoFrameBufferSaveTest(); } if (Core::Input().IsKeyPressed(KeyCode::T)) @@ -291,6 +179,7 @@ namespace lunarium case TestMode::Basic: RenderScene(Core::Graphics()); break; case TestMode::Stress: RenderBatchStressTest(Core::Graphics()); break; case TestMode::String: RenderStringTest(Core::Graphics()); break; + case TestMode::Shapes: RenderShapesTest(Core::Graphics()); break; } @@ -306,6 +195,9 @@ namespace lunarium //std::this_thread::sleep_for (std::chrono::seconds(2)); } + ///////////////////////////////////////////////////////////////////// + // RENDER METHODS RENDER METHODS + ///////////////////////////////////////////////////////////////////// void SimpleRenderScene::RenderScene(Renderer2D& g) { @@ -352,16 +244,32 @@ namespace lunarium } + void SimpleRenderScene::RenderShapesTest(Renderer2D& g) + { + + g.DrawLine(glm::vec2(30.0f, 200.0f), glm::vec2(400.0f, 400.0f), Color::Green(), 3.0f); + + for (auto iter = mLines.begin(); iter != mLines.end(); iter++) + { + g.DrawLine(iter->Position1, iter->Position2, iter->Color, iter->Thickness, iter->Angle); + iter->Angle += iter->RotSpeed; + } + } + + + ///////////////////////////////////////////////////////////////////// + // GUI DRAWING GUI DRAWING + ///////////////////////////////////////////////////////////////////// void SimpleRenderScene::DrawStatsGUI() { - const char* mode_names[3] = { "Basic", "Stress", "String" }; + const char* mode_names[4] = { "Basic", "Stress", "String", "Shapes" }; ImGui::SetNextWindowPos(ImVec2(0, 0), ImGuiCond_FirstUseEver); ImGui::SetNextWindowSize(ImVec2(400, 800)); ImGui::Begin("RENDER INFO"); ImGui::BeginChild("Scene Info", ImVec2(ImGui::GetWindowSize().x - 15, ImGui::GetFrameHeightWithSpacing() * 3.5f), true); ImGui::Text("Scene Info"); ImGui::Separator(); - ImGui::Combo("Scene Mode", (int*)&mTestMode, mode_names, 3); + ImGui::Combo("Scene Mode", (int*)&mTestMode, mode_names, 4); ImGui::EndChild(); ImGui::BeginChild("Per Frame", ImVec2(ImGui::GetWindowSize().x - 15, ImGui::GetFrameHeightWithSpacing() * 3.5f), true); ImGui::Text("Per Frame"); @@ -398,6 +306,15 @@ namespace lunarium mSubTex = Rectangle::MakeFromTopLeft(0.0f, 0.0f, 256.0f, 256.0f); } } + else if (mTestMode == TestMode::Shapes) + { + ImGui::DragInt("Number of Lines", &mNumLines); + if (ImGui::Button("Regenerate Shapes")) + { + GenerateLines(); + GenerateEllipses(); + } + } ImGui::EndChild(); @@ -405,4 +322,153 @@ namespace lunarium mNumQuadsToRender = Math::ClampI(mNumQuadsToRender, 0, NUM_QUADS); } + + + ///////////////////////////////////////////////////////////////////// + // HELPERS HELPERS + ///////////////////////////////////////////////////////////////////// + + void SimpleRenderScene::LoadImages() + { + // Test Image 1 + int w, h, n; + stbi_set_flip_vertically_on_load(0); + unsigned char* buffer = stbi_load("LinkToThePast1_sized.png", &w, &h, &n, 0); + + TextureFormat format = TextureFormat::RGBA; + if (n == 3) + { + format = TextureFormat::RGB; + } + mpTestImageLoad = Texture::Create(buffer, w, h, format, true); + mSrcWidth = w; + mSrcHeight = h; + + delete[] buffer; + + // Debug texture + stbi_set_flip_vertically_on_load(0); + buffer = stbi_load("debug_texture.jpeg", &w, &h, &n, 0); + + format = TextureFormat::RGBA; + if (n == 3) + { + format = TextureFormat::RGB; + } + else if (n == 1) + { + format = TextureFormat::RED; + } + + mpTestImageLoad2 = Texture::Create(buffer, w, h, format); + delete[] buffer; + + // Text testing texture + stbi_set_flip_vertically_on_load(0); + buffer = stbi_load("lunarium_text_test.png", &w, &h, &n, 0); + + format = TextureFormat::RGBA; + if (n == 3) + { + format = TextureFormat::RGB; + } + else if (n == 1) + { + format = TextureFormat::RED; + } + + mpTestImageLoad3 = Texture::Create(buffer, w, h, format); + delete[] buffer; + } + + void SimpleRenderScene::GenerateLines() + { + mLines.clear(); + int window_width = 0; + int window_height = 0; + Core::MainWindow().GetFramebufferSize(&window_width, &window_height); + for (int i = 0; i < mNumLines; i++) + { + mLines.push_back(LineData + { + glm::vec2(rand() % window_width, rand() % window_height), + glm::vec2(rand() % window_width, rand() % window_height), + Color(((float)(rand() % 10000)) / 10000.0f, + ((float)(rand() % 10000)) / 10000.0f, + ((float)(rand() % 10000)) / 10000.0f, + 1.0f), + ((float)(rand() % 180)), + ((float)(rand() % 100)) / 100.0f + 0.01f, + ((float)(rand() % 100)) / 10.0f + 0.5f + }); + } + } + + + void SimpleRenderScene::GenerateEllipses() + { + + } + + void SimpleRenderScene::GenerateQuads() + { + mQuads = new Rectangle[NUM_QUADS]; + for (int i = 0; i < NUM_QUADS; i++) + { + float x = (rand() % 1000); + float y = (rand() % 600); + float w = (rand() % 200) + 10; + float h = (rand() % 200) + 10; + + mQuads[i] = Rectangle(x, y, w, h); + } + + mQuadColors = new Color[NUM_QUADS]; + mQuadTexures = new Texture*[NUM_QUADS]; + + for (int i = 0; i < NUM_QUADS; i++) + { + mQuadTexures[i] = (i % 2 == 0) ? mpTestImageLoad : mpTestImageLoad2; + mQuadColors[i].R = ((float)(rand() % 10000)) / 10000.0f; + mQuadColors[i].G = ((float)(rand() % 10000)) / 10000.0f; + mQuadColors[i].B = ((float)(rand() % 10000)) / 10000.0f; + mQuadColors[i].A = 1.0f; + } + } + + + + void SimpleRenderScene::DoFrameBufferSaveTest() + { + // Test writing out a rendered image with transparency + Renderer2D& g = Core::Graphics(); + Color prev = g.GetClearColor(); + g.SetClearColor(Color(0.0f, 0.0f, 0.0f, 0.0f)); + mFrameBufferTwo->Bind(); + OrthographicCamera cam(Vec2f{0.0f, 0.0f}, Sizef{(float)mFrameBufferTwo->GetTexture()->GetWidth(), (float)mFrameBufferTwo->GetTexture()->GetHeight()}); + g.BeginDraw(&cam); + // if (Failed(result)) + // { + // Logger::Warn(mLogCat, "Unable to render to texture: %s", result.Description.c_str()); + // return; + // } + + Logger::Info(mLogCat, "Running transparent image test"); + + g.DrawQuad(Rectangle(500, 400, 300, 300), Color(0.5f, 0.0f, 0.75f, 1.0f)); + g.DrawQuad(Rectangle(200, 300, 100, 100), Color(0.2f, 0.5f, 0.4f, 1.0f), nullptr, 45.0f); + g.DrawString("This is a test of rendering an image with transparency", + Rectangle::MakeFromTopLeft(50, 50, 600, 200), Color(0.0f, 1.0f, 0.2f, 1.0f), 0.5f); + + g.EndDraw(); + mpRenderedImage = mFrameBufferTwo->GetTexture(); + mFrameBufferTwo->Unbind(); + //mpRenderedImage = Core::GetInstance().EndRenderToTexture(); + g.SetClearColor(prev); + + stbi_flip_vertically_on_write(1); + stbi_write_png("lunarium_test_image.png", mpRenderedImage->GetWidth(), mpRenderedImage->GetHeight(), 4, + mpRenderedImage->GetPixels(), mpRenderedImage->GetWidth() * 4); + //Logger::Info(mLogCat, "") + } } \ No newline at end of file diff --git a/src/run_modes/testbed/scenes/simple_render_scene.h b/src/run_modes/testbed/scenes/simple_render_scene.h index 213793e..65214cc 100644 --- a/src/run_modes/testbed/scenes/simple_render_scene.h +++ b/src/run_modes/testbed/scenes/simple_render_scene.h @@ -26,6 +26,7 @@ namespace lunarium Basic, Stress, String, + Shapes, }; public: SimpleRenderScene(uint32_t logCat); @@ -35,6 +36,7 @@ namespace lunarium void RenderScene(Renderer2D& g); void RenderBatchStressTest(Renderer2D& g); void RenderStringTest(Renderer2D& g); + void RenderShapesTest(Renderer2D& g); private: @@ -71,6 +73,31 @@ namespace lunarium Texture** mQuadTexures; // + // SHAPES MODE DATA + int mNumLines = 100; + struct LineData + { + glm::vec2 Position1; + glm::vec2 Position2; + Color Color; + float Angle; + float RotSpeed; + float Thickness; + }; + std::vector mLines; + + int mNumEllipses = 100; + struct EllipseData + { + glm::vec2 Position; + Color Color; + int Resolution; + float Angle; + float RotSpeed; + }; + std::vector mEllipses; + // + struct GridTestObj { int X; @@ -79,6 +106,12 @@ namespace lunarium private: void DrawStatsGUI(); + void LoadImages(); + void GenerateLines(); + void GenerateEllipses(); + void GenerateQuads(); + + void DoFrameBufferSaveTest(); }; }