diff --git a/docs/Bugs.todo b/docs/Bugs.todo new file mode 100644 index 0000000..e69de29 diff --git a/docs/Tasks.todo b/docs/Tasks.todo index eedcec9..9542289 100644 --- a/docs/Tasks.todo +++ b/docs/Tasks.todo @@ -11,13 +11,15 @@ Core: ✔ Add a new class for font loading/management and text rendering @done (9/7/2021, 3:57:08 PM) ✔ Make the text renderer smarter about breaking up words on multiple lines @low @done (9/8/2021, 2:23:03 PM) ✔ Implement the Image creation methods @done (9/9/2021, 2:50:20 PM) + ☐ Implement Render to Texture GUI: ✔ Dear ImGui class with basic initialization @done (9/10/2021, 1:42:19 PM) ✔ Debug log window @done (9/10/2021, 4:44:48 PM) - ☐ Add key to show debug log window + ✔ Add key to show debug log window @done (9/13/2021, 6:47:44 PM) ☐ Add checkboxes to disable log categories and levels + ☐ Add LUA Console window Input: ✔ Port over the Element2D input system and adjust it to use glfw @done (9/8/2021, 8:20:07 PM) @@ -67,4 +69,8 @@ Editor: Asset Pipeline: - ☐ Read through the contents folder and generate asset files in a custom format (useable by the engine) \ No newline at end of file + ☐ Read through the contents folder and generate asset files in a custom format (useable by the engine) + +Tester: + - A special class that is used to unit-test features of the engine + \ No newline at end of file diff --git a/scripts/cmconfig.bat b/scripts/cmconfig.bat index 8901304..e466c5c 100644 --- a/scripts/cmconfig.bat +++ b/scripts/cmconfig.bat @@ -3,4 +3,4 @@ REM This script expects to be run from the parent directory REM ex. scripts/cmconfig.bat @echo on -cmake -DGLFW_BUILD_DOCS=OFF -B build/ -S . -G "Visual Studio 16 2019" -A x64 \ No newline at end of file +cmake -Wno-dev -DGLFW_BUILD_DOCS=OFF -B build/ -S . -G "Visual Studio 16 2019" -A x64 \ No newline at end of file diff --git a/src/core/core.cpp b/src/core/core.cpp index f804a11..95f0752 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -225,6 +225,14 @@ namespace lunarium // Update game state + mpGraphics->BeginDraw(RenderTarget::RT_IMAGE); + + // DEBUG: Graphics tests + mpGraphics->DrawFilledEllipse(glm::vec2(600, 300), glm::vec2(100, 150), Color(1.0f, 0.0f, 1.0f, 1.0f), 100); + mpGraphics->DrawString("This is a test of the text renderer!", Rectangle(100, 200, width, 300), + Color(0.0f, 1.0f, 1.0f, 1.0f), 0.5f, mpGraphics->DefaultFont()); + Image* pImage = mpGraphics->EndDraw(); + // Render mGUI.NewFrame(); mpGraphics->BeginDraw(); @@ -233,13 +241,12 @@ namespace lunarium // mGUI.ShowDemoWindow(); LogGui::GetInstance().Show(); - // DEBUG: Graphics tests - mpGraphics->DrawFilledEllipse(glm::vec2(600, 300), glm::vec2(100, 150), Color(1.0f, 0.0f, 1.0f, 1.0f), 100); - mpGraphics->DrawString("This is a test of the text renderer!", Rectangle(100, 200, width, 300), - Color(0.0f, 1.0f, 1.0f, 1.0f), 0.5f, mpGraphics->DefaultFont()); + mpGraphics->DrawImage(*pImage, glm::vec2(0.0f, 0.0f), Color(1.0f, 1.0f, 1.0f, 1.0f)); mGUI.EndFrame(); mpGraphics->EndDraw(); + + // delete pImage; } } } \ No newline at end of file diff --git a/src/graphics/definitions.h b/src/graphics/definitions.h new file mode 100644 index 0000000..c8cb65a --- /dev/null +++ b/src/graphics/definitions.h @@ -0,0 +1,23 @@ +/****************************************************************************** +* File - definitions.h +* Author - Joey Pollack +* Date - 2021/09/14 (y/m/d) +* Mod Date - 2021/09/14 (y/m/d) +* Description - Common graphics definitions +******************************************************************************/ + +#ifndef DEFINITIONS_H_ +#define DEFINITIONS_H_ + +namespace lunarium +{ + enum ImageFormat + { + RGB, + RGBA, + BGR, + BGRA + }; +} + +#endif // DEFINITIONS_H_ \ No newline at end of file diff --git a/src/graphics/gui/logGui.cpp b/src/graphics/gui/logGui.cpp index b07c230..192d102 100644 --- a/src/graphics/gui/logGui.cpp +++ b/src/graphics/gui/logGui.cpp @@ -43,7 +43,7 @@ namespace lunarium //////////////////////////////////////////////////////////// LogGui* LogGui::mpInstance = nullptr; LogGui::LogGui() - : mbShow(true), mListener(this), mbOglDebug(false) + : mbShow(true), mListener(this), mbOglDebug(false), mbInfoVerbose(false) { } @@ -83,14 +83,18 @@ namespace lunarium ImGui::End(); return; } - + ImGui::BeginChild("Message Types", ImVec2(0.0f, 20.0f)); ImGui::Checkbox("OGL_DEBUG", &mbOglDebug); + ImGui::SameLine(); + ImGui::Checkbox("INFO_VERBOSE", &mbInfoVerbose); + ImGui::EndChild(); ImGui::Separator(); ImGui::BeginChild("scrolling", ImVec2(0, 0), false, ImGuiWindowFlags_HorizontalScrollbar); ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0)); for (int i = 0; i < mMsgHistory.size(); i++) { - if (mMsgHistory[i].find("[OGL_DEBUG]") != std::string::npos && !mbOglDebug) + if ((mMsgHistory[i].find("[OGL_DEBUG]") != std::string::npos && !mbOglDebug) + || (mMsgHistory[i].find("[INFO_VERBOSE]") != std::string::npos && !mbInfoVerbose)) { continue; } diff --git a/src/graphics/gui/logGui.h b/src/graphics/gui/logGui.h index 916d22d..6aa5abd 100644 --- a/src/graphics/gui/logGui.h +++ b/src/graphics/gui/logGui.h @@ -48,6 +48,7 @@ namespace lunarium GuiListener mListener; bool mbOglDebug; + bool mbInfoVerbose; private: LogGui(); diff --git a/src/graphics/igraphics.h b/src/graphics/igraphics.h index c2dfee6..4e67ec4 100644 --- a/src/graphics/igraphics.h +++ b/src/graphics/igraphics.h @@ -10,6 +10,7 @@ #ifndef IGRAPHICS_H_ #define IGRAPHICS_H_ +#include "definitions.h" #include #include @@ -19,12 +20,12 @@ namespace lunarium class Window; class Image; - enum ImageFormat + + + enum RenderTarget { - RGB, - RGBA, - BGR, - BGRA + RT_WINDOW, + RT_IMAGE }; class IGraphics @@ -39,8 +40,10 @@ namespace lunarium virtual void ResizeCanvas() = 0; - virtual void BeginDraw() = 0; - virtual void EndDraw() = 0; + // If render target is set to image the image will be the same + // size as the window + virtual void BeginDraw(RenderTarget rt = RenderTarget::RT_WINDOW) = 0; + virtual Image* EndDraw() = 0; public: // @@ -73,6 +76,7 @@ namespace lunarium bool mbIsInit; int mDefaultFont; Color mClearColor; + Image* mpFBTexture; }; } diff --git a/src/graphics/image.cpp b/src/graphics/image.cpp index 4efafc3..3ca9175 100644 --- a/src/graphics/image.cpp +++ b/src/graphics/image.cpp @@ -8,9 +8,49 @@ ******************************************************************************/ #include "image.h" +#include namespace lunarium { + + Image::Image() + : mRawData(nullptr), mRawDataSize(0), mWidth(0), mHeight(0) + { + } + + Image::~Image() + { + delete[] mRawData; + mRawData = nullptr; + } + + + Image::Image(const Image& rhs) + : mRawData(nullptr), mRawDataSize(0), mWidth(0), mHeight(0) + { + *this = rhs; + } + + const Image& Image::operator=(const Image& rhs) + { + if (this == &rhs) + { + return *this; + } + + FreeRawData(); + mGLTextureID = rhs.mGLTextureID; + mFormat = rhs.mFormat; + mWidth = rhs.mWidth; + mHeight = rhs.mHeight; + mRawDataSize = rhs.mRawDataSize; + + mRawData = new unsigned char[mRawDataSize]; + memcpy(mRawData, rhs.mRawData, mRawDataSize); + + return *this; + } + unsigned int Image::GetGLTextureID() const { return mGLTextureID; @@ -26,23 +66,16 @@ namespace lunarium return mHeight; } - void Image::FreeRawData() + ImageFormat Image::GetFormat() const { - delete[] mRawData; - mRawData = nullptr; - - mRawDataSize = 0; + return mFormat; } - Image::Image() - : mRawData(nullptr), mRawDataSize(0), mWidth(0), mHeight(0) - { - } - - Image::~Image() + void Image::FreeRawData() { delete[] mRawData; mRawData = nullptr; - } + mRawDataSize = 0; + } } diff --git a/src/graphics/image.h b/src/graphics/image.h index a9a0cc9..5ca62c3 100644 --- a/src/graphics/image.h +++ b/src/graphics/image.h @@ -10,6 +10,7 @@ #ifndef IMAGE_H_ #define IMAGE_H_ +#include "definitions.h" namespace lunarium { @@ -23,6 +24,7 @@ namespace lunarium unsigned int GetGLTextureID() const; int GetWidth() const; int GetHeight() const; + ImageFormat GetFormat() const; void FreeRawData(); @@ -30,11 +32,14 @@ namespace lunarium Image(); ~Image(); + Image(const Image& rhs); + const Image& operator=(const Image& rhs); unsigned char* mRawData; int mRawDataSize; int mWidth; int mHeight; + ImageFormat mFormat; unsigned int mGLTextureID; }; diff --git a/src/graphics/opengl/glGraphics.cpp b/src/graphics/opengl/glGraphics.cpp index 08caf6e..9b5a109 100644 --- a/src/graphics/opengl/glGraphics.cpp +++ b/src/graphics/opengl/glGraphics.cpp @@ -58,7 +58,8 @@ namespace lunarium } mpWindow = pWindow; - ResizeCanvas(); + mpFBTexture = new Image; + ResizeCanvas(); // Also calls InitTextureFrameBuffer glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -104,26 +105,59 @@ namespace lunarium void OglGraphics::ResizeCanvas() { // Get viewport size from glfw window - int width = 0; - int height = 0; - glfwGetFramebufferSize(mpWindow->GetWindow(), &width, &height); + glfwGetFramebufferSize(mpWindow->GetWindow(), &mFBWidth, &mFBHeight); - glViewport(0, 0, width, height); - mProjection = glm::ortho(0.0f, (GLfloat)width, (GLfloat)height, 0.0f, -1.0f, 1.0f); + glViewport(0, 0, mFBWidth, mFBHeight); + mProjection = glm::ortho(0.0f, (GLfloat)mFBWidth, (GLfloat)mFBHeight, 0.0f, -1.0f, 1.0f); Logger::Log(LogCategory::GRAPHICS, LogLevel::INFO_VERBOSE, - "glViewport set to %d, %d", width, height); + "glViewport set to %d, %d", mFBWidth, mFBHeight); + + InitTextureFrameBuffer(); } - void OglGraphics::BeginDraw() + void OglGraphics::BeginDraw(RenderTarget rt) { + mRT = rt; + + if (mRT == RenderTarget::RT_IMAGE) + { + glBindFramebuffer(GL_FRAMEBUFFER, mFBO); + } + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } - void OglGraphics::EndDraw() + Image* OglGraphics::EndDraw() { - mpWindow->SwapBuffers(); + if (mRT == RenderTarget::RT_IMAGE) + { + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glBindTexture(GL_TEXTURE_2D, mpFBTexture->mGLTextureID); + + // Buffer width and height (in pixels) is the same as the screen size + // Need to multiply these by the number bytes per pixel + int bufferSize = mFBWidth * mFBHeight * 4; // NOTE: Assuming 4 channels for now + unsigned char* buffer = new unsigned char[bufferSize]; + glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, (void*)buffer); + + mpFBTexture->FreeRawData(); + mpFBTexture->mWidth = mFBWidth; + mpFBTexture->mHeight = mFBHeight; + mpFBTexture->mRawData = buffer; + mpFBTexture->mRawDataSize = bufferSize; + mpFBTexture->mFormat = ImageFormat::RGBA; + + // return a copy of the image + return new Image(*mpFBTexture); + } + else + { + mpWindow->SwapBuffers(); + return nullptr; + } + } //////////////////////////////////////////////////////////// @@ -274,11 +308,13 @@ namespace lunarium glm::mat4 trans = glm::translate(id, pos); trans = glm::scale(trans, glm::vec3(destination.Width, destination.Height, 1.0f)); + mImageShader.MakeActive(); + // float widthDiff = image.GetWidth() - source.Width; // if (source.Width == image.GetWidth() && source.Height == image.GetHeight()) // { - // mImageShader.MakeActive(); + // mImageShader.SetUniformf("uvManip", { 1.0f, 0.0f, 1.0f, 0.0f }); // No uv Manipulation // mImageShader.SetUniformMatrix("model", 1, glm::value_ptr(trans)); // mImageShader.SetUniformMatrix("projection", 1, glm::value_ptr(mProjection)); @@ -293,6 +329,8 @@ namespace lunarium float yScale = source.Height / image.GetHeight(); float yOffset = source.Top / image.GetHeight(); + Logger::Log(LogCategory::GRAPHICS, LogLevel::INFO_VERBOSE, "uvManip Values: %f, %f, %f, %f", xScale, xOffset, yScale, yOffset); + mImageShader.SetUniformf("uvManip", { xScale, xOffset, yScale, yOffset }); mImageShader.SetUniformMatrix("model", 1, glm::value_ptr(trans)); mImageShader.SetUniformMatrix("projection", 1, glm::value_ptr(mProjection)); @@ -432,15 +470,6 @@ namespace lunarium } } - void OglGraphics::InitTextSystem() - { - // TODO: Check to see if Dear ImGui can be used to render text - // If it can render text on the app window and doesn't need - // to render onto one of it's own windows then it should work. - // If not add FreeType to the project and put the text rendering - // into it's own class. - } - void OglGraphics::InitShapeSystem() { // Create rectangle buffers @@ -474,4 +503,39 @@ namespace lunarium Logger::Log(LogCategory::GRAPHICS, LogLevel::WARNING, "Unable to build shape shader program."); } } + + void OglGraphics::InitTextureFrameBuffer() + { + // Frame buffer + glGenFramebuffers(1, &mFBO); + glBindFramebuffer(GL_FRAMEBUFFER, mFBO); + + // Texture + glGenTextures(1, &mpFBTexture->mGLTextureID); + glBindTexture(GL_TEXTURE_2D, mpFBTexture->mGLTextureID); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, mFBWidth, mFBHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glBindTexture(GL_TEXTURE_2D, 0); + + // Attach texture + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mpFBTexture->mGLTextureID, 0); + + // Render Buffer for depth/stencil testing + glGenRenderbuffers(1, &mRBO); + glBindRenderbuffer(GL_RENDERBUFFER, mRBO); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, mFBWidth, mFBHeight); + glBindRenderbuffer(GL_RENDERBUFFER, 0); + + // Atach the render buffer + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, mRBO); + + + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) + { + Logger::Log(LogCategory::GRAPHICS, LogLevel::WARNING, "Unable to initialize framebuffer for rendering to a texture"); + } + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + } } \ No newline at end of file diff --git a/src/graphics/opengl/glGraphics.h b/src/graphics/opengl/glGraphics.h index 68068f1..64e41a3 100644 --- a/src/graphics/opengl/glGraphics.h +++ b/src/graphics/opengl/glGraphics.h @@ -31,8 +31,11 @@ namespace lunarium virtual void ResizeCanvas(); - virtual void BeginDraw(); - virtual void EndDraw(); + virtual void BeginDraw(RenderTarget rt = RenderTarget::RT_WINDOW); + + /// The image returned by this method is dynamic + /// and needs to be cleaned up + virtual Image* EndDraw(); public: // @@ -64,6 +67,15 @@ namespace lunarium Window* mpWindow; glm::mat4 mProjection; + // Viewport/Framebuffer width and height + int mFBWidth; + int mFBHeight; + + // Objects for rendering to texture + unsigned int mFBO; + unsigned int mRBO; // for depth and stencil + RenderTarget mRT; + // TEXT glText mText; @@ -83,8 +95,8 @@ namespace lunarium private: // Helper Initializers void InitDebugMsgSystem(); void InitImageSystem(); - void InitTextSystem(); void InitShapeSystem(); + void InitTextureFrameBuffer(); private: // Helper methods