Render to texture implemented - need to flip the resulting image vertically

Gui_Panel_Refactor
Joeyrp 4 years ago
parent 54982faa24
commit e0adc0dc28

@ -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)
☐ 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

@ -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
cmake -Wno-dev -DGLFW_BUILD_DOCS=OFF -B build/ -S . -G "Visual Studio 16 2019" -A x64

@ -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;
}
}
}

@ -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_

@ -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;
}

@ -48,6 +48,7 @@ namespace lunarium
GuiListener mListener;
bool mbOglDebug;
bool mbInfoVerbose;
private:
LogGui();

@ -10,6 +10,7 @@
#ifndef IGRAPHICS_H_
#define IGRAPHICS_H_
#include "definitions.h"
#include <utils/types.h>
#include <utils/opRes.h>
@ -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;
};
}

@ -8,9 +8,49 @@
******************************************************************************/
#include "image.h"
#include <cstring>
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;
}
}

@ -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;
};

@ -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);
}
}

@ -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

Loading…
Cancel
Save