Renderer now supports multiple arbitrarily sized frame buffers

Gui_Panel_Refactor
Joeyrp 4 years ago
parent ca9d25073e
commit 7039b1e26b

@ -24,7 +24,7 @@ Core:
✔ Test rotation of images @done (11/1/2021, 2:11:13 PM)
☐ Fix line rotation @low
✔ Add Roboto-Regular.ttf as an internal font @high @done (11/3/2021, 8:35:51 PM)
Allow an image size to be passed in for rendering to an image @high
Allow an image size to be passed in for rendering to an image @high @done (2/3/2022, 4:07:33 PM)
GUI:

@ -368,7 +368,7 @@ namespace lunarium
}
}
OpRes Core::BeginRenderToTexture()
OpRes Core::BeginRenderToTexture(int id)
{
if (mbMidRender)
{
@ -376,7 +376,7 @@ namespace lunarium
}
mbMidTextureRender = true;
mpGraphics->BeginDraw(RenderTarget::RT_IMAGE);
mpGraphics->BeginDraw(id);
return OpRes::OK();
}

@ -41,7 +41,7 @@ namespace lunarium
void RunGameLoop();
OpRes BeginRenderToTexture();
OpRes BeginRenderToTexture(int id);
Image* EndRenderToTexture();

@ -30,16 +30,16 @@ namespace lunarium
protected: // Interface methods for use only by the engine
friend Core;
IGraphics() : mbIsInit(false), mpFBTexture(nullptr) {}
IGraphics() : mbIsInit(false) {}
virtual OpRes Initialize(Window* pWindow, bool enableDebugMessages = true) = 0;
virtual void Shutdown() = 0;
virtual void ResizeCanvas() = 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;
// framebuffer is the ID of the texture/framebuffer to render to
// -1 means draw to the default (most likely the main window) buffer
virtual void BeginDraw(int framebuffer = -1) = 0;
virtual Image* EndDraw() = 0;
public: //
@ -47,6 +47,8 @@ namespace lunarium
virtual void SetClearColor(Color c) = 0;
virtual Color GetClearColor() const = 0;
virtual int CreateRenderTexture(int width, int height, int channels) = 0;
// Draw Methods
virtual void DrawFilledPolygon(float* pVerts, int numVerts, Color color, glm::vec2 position, float angle = 0.0f) = 0;
virtual void DrawLine(glm::vec2 point1, glm::vec2 point2, Color color, float lineWidth, float angle = 0.0f) = 0;
@ -71,7 +73,6 @@ namespace lunarium
bool mbIsInit;
int mDefaultFont;
Color mClearColor;
Image* mpFBTexture;
};
}

@ -29,6 +29,10 @@ namespace lunarium
void GLAPIENTRY MessageCallback(GLenum source, GLenum type, GLuint id,
GLenum severity, GLsizei length, const GLchar* message, const void* userParam)
{
if (type == GL_DEBUG_TYPE_ERROR)
{
Logger::Log(LogCategory::GRAPHICS, LogLevel::ERROR, "OPENGL ERROR");
}
Logger::Log(LogCategory::GRAPHICS, LogLevel::OGL_DEBUG,
"%s (type: %s, source: %s, severity: %s), message: %s",
@ -60,7 +64,6 @@ namespace lunarium
}
mpWindow = pWindow;
mpFBTexture = new Image;
ResizeCanvas(); // Also calls InitTextureFrameBuffer
glEnable(GL_BLEND);
@ -100,41 +103,41 @@ namespace lunarium
void OglGraphics::Shutdown()
{
// Nothing to clean up at this point
// TODO: Clean up frame buffers
}
void OglGraphics::ResizeCanvas()
{
// Get viewport size from glfw window
glfwGetFramebufferSize(mpWindow->GetWindow(), &mFBWidth, &mFBHeight);
glViewport(0, 0, mFBWidth, mFBHeight);
mProjection = glm::ortho(0.0f, (GLfloat)mFBWidth, (GLfloat)mFBHeight, 0.0f, -1.0f, 1.0f);
// mProjection = glm::ortho(0.0f, (GLfloat)mFBWidth, 0.0f, (GLfloat)mFBHeight, -1.0f, 1.0f);
// NOTE: METHOD IS NO LONGER NEEDED
Logger::Log(LogCategory::GRAPHICS, LogLevel::INFO_VERBOSE,
"glViewport set to %d, %d", mFBWidth, mFBHeight);
InitTextureFrameBuffer();
}
void OglGraphics::BeginDraw(RenderTarget rt)
void OglGraphics::BeginDraw(int framebuffer)
{
mRT = rt;
int width = 0, height = 0;
mpWindow->GetFramebufferSize(&width, &height);
mActiveFrameBuffer = framebuffer;
if (mFBWidth != width || mFBHeight != height)
if (mActiveFrameBuffer > -1)
{
ResizeCanvas();
}
mFBWidth = mFrameBuffers[mActiveFrameBuffer]->Texture.GetWidth();
mFBHeight = mFrameBuffers[mActiveFrameBuffer]->Texture.GetHeight();
glViewport(0, 0, mFBWidth, mFBHeight);
mProjection = glm::ortho(0.0f, (GLfloat)mFBWidth, (GLfloat)mFBHeight, 0.0f, -1.0f, 1.0f);
glBindFramebuffer(GL_FRAMEBUFFER, mFrameBuffers[mActiveFrameBuffer]->FBO);
if (mRT == RenderTarget::RT_IMAGE)
}
else
{
glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
int width = 0, height = 0;
mpWindow->GetFramebufferSize(&width, &height);
if (mFBWidth != width || mFBHeight != height)
{
mFBWidth = width;
mFBHeight = height;
glViewport(0, 0, mFBWidth, mFBHeight);
mProjection = glm::ortho(0.0f, (GLfloat)mFBWidth, (GLfloat)mFBHeight, 0.0f, -1.0f, 1.0f);
}
}
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
@ -142,27 +145,26 @@ namespace lunarium
Image* OglGraphics::EndDraw()
{
if (mRT == RenderTarget::RT_IMAGE)
if (mActiveFrameBuffer > -1)
{
FrameBuffer* fb = mFrameBuffers[mActiveFrameBuffer];
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindTexture(GL_TEXTURE_2D, mpFBTexture->GetGLTextureID());
// 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
// TODO: Preallocate the buffer so we don't call new every frame!
unsigned char* buffer = new unsigned char[bufferSize];
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, (void*)buffer);
// FlipImageVertically(buffer, mFBWidth, mFBHeight, 1);
// mpFBTexture->FreeRawData();
mpFBTexture->SetData(buffer);
mpFBTexture->SetWidth(mFBWidth);
mpFBTexture->SetHeight(mFBHeight);
mpFBTexture->SetFormat(ImageFormat::RGBA);
// return a copy of the image
return mpFBTexture;
glBindTexture(GL_TEXTURE_2D, fb->Texture.GetGLTextureID());
if (fb->Texture.GetFormat() == ImageFormat::RGBA)
{
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, (void*)fb->Buffer);
Logger::Log(LogCategory::GRAPHICS, LogLevel::INFO, "RGBA ID: %d", mActiveFrameBuffer);
}
else if (fb->Texture.GetFormat() == ImageFormat::RGB)
{
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, (void*)fb->Buffer);
Logger::Log(LogCategory::GRAPHICS, LogLevel::INFO, "RGB ID: %d", mActiveFrameBuffer);
}
fb->Texture.SetData(fb->Buffer);
return &fb->Texture;
}
else
{
@ -188,6 +190,74 @@ namespace lunarium
return mClearColor;
}
int OglGraphics::CreateRenderTexture(int width, int height, int channels)
{
FrameBuffer* fb = new FrameBuffer;
fb->Texture.SetWidth(width);
fb->Texture.SetHeight(height);
GLint format = -1;
if (3 == channels)
{
fb->Texture.SetFormat(ImageFormat::RGB);
format = GL_RGB;
}
else if (4 == channels)
{
fb->Texture.SetFormat(ImageFormat::RGBA);
format = GL_RGBA;
}
else
{
Logger::Log(LogCategory::GRAPHICS, LogLevel::ERROR, "OglGraphics::CreateRenderTexture failed - invalid channels value: %n", channels);
return -1;
}
// Frame buffer
glGenFramebuffers(1, &fb->FBO);
glBindFramebuffer(GL_FRAMEBUFFER, fb->FBO);
// Texture
unsigned int id = -1;
glGenTextures(1, &id);
fb->Texture.SetGLTextureID(id);
glBindTexture(GL_TEXTURE_2D, fb->Texture.GetGLTextureID());
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, 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, fb->Texture.GetGLTextureID(), 0);
// Render Buffer for depth/stencil testing
glGenRenderbuffers(1, &fb->RBO);
glBindRenderbuffer(GL_RENDERBUFFER, fb->RBO);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
// Atach the render buffer
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fb->RBO);
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);
return -1;
}
// finalize the FrameBuffer object
fb->Buffer = new unsigned char[width * height * channels];
fb->Texture.SetData(nullptr);
int next_id = mFrameBuffers.size();
mFrameBuffers[next_id] = fb;
glBindFramebuffer(GL_FRAMEBUFFER, 0);
return next_id;
}
// Draw Methods
void OglGraphics::DrawLine(glm::vec2 point1, glm::vec2 point2, Color color, float lineWidth, float angle)
{
@ -585,38 +655,41 @@ namespace lunarium
void OglGraphics::InitTextureFrameBuffer()
{
// NOTE: METHOD IS NO LONGER NEEDED
// Frame buffer
glGenFramebuffers(1, &mFBO);
glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
// glGenFramebuffers(1, &mFBO);
// glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
// Texture
unsigned int id = -1;
glGenTextures(1, &id);
mpFBTexture->SetGLTextureID(id);
glBindTexture(GL_TEXTURE_2D, mpFBTexture->GetGLTextureID());
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, mFBWidth, mFBHeight, 0, GL_RGBA, 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);
// // Texture
// unsigned int id = -1;
// glGenTextures(1, &id);
// mpFBTexture->SetGLTextureID(id);
// glBindTexture(GL_TEXTURE_2D, mpFBTexture->GetGLTextureID());
// glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, mFBWidth, mFBHeight, 0, GL_RGBA, 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->GetGLTextureID(), 0);
// // Attach texture
// glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mpFBTexture->GetGLTextureID(), 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);
// // 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);
// // 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");
}
// 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);
// glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
}

@ -13,6 +13,7 @@
#include <glad/gl.h>
#include "glShader.h"
#include "glText.h"
#include <assets/types/image.h>
#include <map>
#include <string>
@ -31,7 +32,7 @@ namespace lunarium
virtual void ResizeCanvas();
virtual void BeginDraw(RenderTarget rt = RenderTarget::RT_WINDOW);
virtual void BeginDraw(int framebuffer = -1); // -1 means draw to the window/default frame buffer
/// The image returned by this method is dynamic
/// and needs to be cleaned up
@ -42,6 +43,8 @@ namespace lunarium
virtual void SetClearColor(Color c);
virtual Color GetClearColor() const;
virtual int CreateRenderTexture(int width, int height, int channels);
// Draw Methods
virtual void DrawFilledPolygon(float* pVerts, int numVerts, Color color, glm::vec2 position, float angle = 0.0f);
virtual void DrawLine(glm::vec2 point1, glm::vec2 point2, Color color, float lineWidth, float angle = 0.0f);
@ -70,9 +73,15 @@ namespace lunarium
int mFBHeight;
// Objects for rendering to texture
unsigned int mFBO;
unsigned int mRBO; // for depth and stencil
RenderTarget mRT;
struct FrameBuffer
{
Image Texture;
unsigned char* Buffer;
unsigned int FBO;
unsigned int RBO; // for depth and stencil
};
std::map<int, FrameBuffer*> mFrameBuffers;
int mActiveFrameBuffer;
// TEXT
glText mText;

@ -38,6 +38,10 @@ namespace lunarium
mImageSize.Width = 1280;
mImageSize.Height = 720;
// Create the render textures
mFrameBufferOne = Core::Graphics().CreateRenderTexture(mImageSize.Width, mImageSize.Height, 4);
mFrameBufferTwo = Core::Graphics().CreateRenderTexture(1024, 1024, 4);
angle = 0.0f;
box_angle = 0.0f;
@ -94,7 +98,7 @@ namespace lunarium
IGraphics& g = Core::Graphics();
Color prev = g.GetClearColor();
g.SetClearColor(Color(0.0f, 0.0f, 0.0f, 0.0f));
OpRes result = Core::GetInstance().BeginRenderToTexture();
OpRes result = Core::GetInstance().BeginRenderToTexture(mFrameBufferTwo);
if (Failed(result))
{
Logger::Log(mLogCat, LogLevel::WARNING, "Unable to render to texture: %s", result.Description.c_str());
@ -119,7 +123,7 @@ namespace lunarium
mImageSize.Height = Math::ClampI(mImageSize.Height, 180, 720);
// Render to texture testing
OpRes result = Core::GetInstance().BeginRenderToTexture();
OpRes result = Core::GetInstance().BeginRenderToTexture(mFrameBufferOne);
if (Failed(result))
{
Logger::Log(mLogCat, LogLevel::WARNING, "Unable to render to texture: %s", result.Description.c_str());
@ -144,10 +148,10 @@ namespace lunarium
g->DrawImage(*mpRenderedImage, Rectangle::MakeFromTopLeft(0.0f, 0.0f, (float)mpRenderedImage->GetWidth(), (float)mpRenderedImage->GetHeight()),
Rectangle::MakeFromTopLeft(0.0f, 0.0f, (float)mImageSize.Width, (float)mImageSize.Height), Color(1.0f, 1.0f, 1.0f, 1.0f), angle);
// g->DrawBox(Rectangle::MakeFromTopLeft(0.0f, 0.0f, (float)mImageSize.Width, (float)mImageSize.Height), Color(0.0f, 0.0f, 0.0f, 1.0f), 1.0f, angle);
g->DrawBox(Rectangle::MakeFromTopLeft(0.0f, 0.0f, (float)mImageSize.Width, (float)mImageSize.Height), Color(0.0f, 0.0f, 0.0f, 1.0f), 1.0f, angle);
// g->DrawBox(Rectangle(400, 400, 128.0f, 128.0f), Color(0.0f, 1.0f, 0.0f, 1.0f), 2.0f, box_angle);
g->DrawBox(Rectangle(400, 400, 128.0f, 128.0f), Color(0.0f, 1.0f, 0.0f, 1.0f), 2.0f, box_angle);
// g->DrawString((*mGrid[{-2, 0,}])->msg.c_str(), Rectangle::MakeFromTopLeft(200.0f, 500.0f, 500.0f, 200.0f), Color(0.5f, 0.0f, 0.75f, 1.0f));
g->DrawString((*mGrid[{-2, 0,}])->msg.c_str(), Rectangle::MakeFromTopLeft(200.0f, 500.0f, 500.0f, 200.0f), Color(0.5f, 0.0f, 0.75f, 1.0f));
}
}

@ -31,6 +31,8 @@ namespace lunarium
int mTextBoxWidth;
Sizei mImageSize;
Image* mpRenderedImage;
int mFrameBufferOne;
int mFrameBufferTwo;
float angle;
float box_angle;

@ -30,9 +30,9 @@ namespace lunarium
mLogCat = Logger::RegisterCategory("TESTER");
#if BUILD_NO_EDITOR
Logger::Log(mLogCat, LogLevel::INFO, "BUILDING NO EDITOR!");
Logger::Log(mLogCat, LogLevel::INFO, "NO EDITOR!");
#else
Logger::Log(mLogCat, LogLevel::INFO, "BUILDING WITH THE EDITOR!");
Logger::Log(mLogCat, LogLevel::INFO, "EDITOR DETECTED!");
#endif
mpScene = new SimpleRenderScene(mLogCat);

Loading…
Cancel
Save