174 lines
4.1 KiB
C++
174 lines
4.1 KiB
C++
#include "Framebuffer.h"
|
|
#include <glad/glad.h>
|
|
#include <Tracy.hpp>
|
|
|
|
namespace Nuake
|
|
{
|
|
FrameBuffer::FrameBuffer(bool hasRenderBuffer, Vector2 size)
|
|
{
|
|
m_Textures = std::map<int, Ref<Texture>>();
|
|
m_Size = size;
|
|
m_HasRenderBuffer = hasRenderBuffer;
|
|
|
|
glGenFramebuffers(1, &m_FramebufferID);
|
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_FramebufferID);
|
|
|
|
// Create render buffer and attach to frame buffer.
|
|
if (m_HasRenderBuffer)
|
|
{
|
|
glGenRenderbuffers(1, &m_RenderBuffer);
|
|
glBindRenderbuffer(GL_RENDERBUFFER, m_RenderBuffer);
|
|
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, static_cast<int>(m_Size.x), static_cast<int>(m_Size.y));
|
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_RenderBuffer);
|
|
}
|
|
else
|
|
{
|
|
m_RenderBuffer = -1;
|
|
}
|
|
|
|
// Unbind
|
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
|
}
|
|
|
|
FrameBuffer::~FrameBuffer()
|
|
{
|
|
glDeleteFramebuffers(1, &m_FramebufferID);
|
|
glDeleteRenderbuffers(1, &m_RenderBuffer);
|
|
}
|
|
|
|
void FrameBuffer::SetTexture(Ref<Texture> texture, GLenum attachment)
|
|
{
|
|
m_Textures[attachment] = texture;
|
|
// Attach texture to the framebuffer.
|
|
Bind();
|
|
texture->AttachToFramebuffer(attachment);
|
|
|
|
// Set draw buffer with dynamic amount of render target.
|
|
// Surely, this can be optimized.
|
|
int size = 0;
|
|
std::vector<unsigned int> keys = std::vector<unsigned int>();
|
|
for (auto& s : m_Textures)
|
|
{
|
|
if (s.first == GL_DEPTH_ATTACHMENT)
|
|
continue;
|
|
|
|
keys.push_back(s.first);
|
|
size += 1;
|
|
}
|
|
|
|
if (size > 0)
|
|
glDrawBuffers(size, &keys[0]);
|
|
|
|
Unbind();
|
|
}
|
|
|
|
|
|
void FrameBuffer::Clear()
|
|
{
|
|
ZoneScoped;
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
}
|
|
|
|
void FrameBuffer::Bind()
|
|
{
|
|
ZoneScoped;
|
|
if (ResizeQueued)
|
|
UpdateSize(m_Size);
|
|
|
|
glBindFramebuffer(GL_FRAMEBUFFER, m_FramebufferID);
|
|
|
|
glViewport(0, 0, static_cast<int>(m_Size.x), static_cast<int>(m_Size.y));
|
|
}
|
|
|
|
void FrameBuffer::Unbind()
|
|
{
|
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
}
|
|
|
|
void FrameBuffer::QueueResize(Vector2 size)
|
|
{
|
|
ZoneScoped;
|
|
|
|
if (size == m_Size)
|
|
return;
|
|
|
|
ResizeQueued = true;
|
|
m_Size = size;
|
|
}
|
|
|
|
void FrameBuffer::UpdateSize(Vector2 size)
|
|
{
|
|
ZoneScoped;
|
|
m_Size = size;
|
|
ResizeQueued = false;
|
|
|
|
// Delete frame buffer and render buffer.
|
|
glDeleteFramebuffers(1, &m_FramebufferID);
|
|
if(m_HasRenderBuffer)
|
|
glDeleteRenderbuffers(1, &m_RenderBuffer);
|
|
|
|
// New FBO and RBO.
|
|
glGenFramebuffers(1, &m_FramebufferID);
|
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_FramebufferID);
|
|
|
|
// Recreate resized texture.
|
|
for (auto& t : m_Textures)
|
|
{
|
|
t.second->Resize(size);
|
|
SetTexture(t.second, t.first);
|
|
}
|
|
|
|
// Recreate render buffer
|
|
// TODO: move out render buffer.
|
|
if (m_HasRenderBuffer)
|
|
{
|
|
glGenRenderbuffers(1, &m_RenderBuffer);
|
|
glBindRenderbuffer(GL_RENDERBUFFER, m_RenderBuffer);
|
|
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, static_cast<int>(m_Size.x), static_cast<int>(m_Size.y));
|
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_RenderBuffer);
|
|
}
|
|
|
|
// Unbind.
|
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
|
}
|
|
|
|
int FrameBuffer::ReadPixel(uint32_t attachment, const Vector2 coords)
|
|
{
|
|
glReadBuffer(GL_COLOR_ATTACHMENT0 + attachment);
|
|
int pixelData;
|
|
glReadPixels((int)coords.x, (int)coords.y, 1, 1, GL_RED_INTEGER, GL_INT, &pixelData);
|
|
return pixelData;
|
|
}
|
|
|
|
Vector2 FrameBuffer::ReadVec2(uint32_t attachment, const Vector2 coords)
|
|
{
|
|
glReadBuffer(GL_COLOR_ATTACHMENT0 + attachment);
|
|
unsigned char pixelData[2]; // Store two components for the vec2 (byte)
|
|
glReadPixels((int)coords.x, (int)coords.y, 1, 1, GL_RG, GL_UNSIGNED_BYTE, &pixelData);
|
|
// Normalize the values (unsigned byte to [0, 1] float)
|
|
return Vector2(pixelData[0] / 255.0f, pixelData[1] / 255.0f);
|
|
}
|
|
|
|
float FrameBuffer::ReadDepth(const Vector2& coords)
|
|
{
|
|
glReadBuffer(GL_DEPTH_ATTACHMENT);
|
|
float pixelData;
|
|
glReadPixels((int)coords.x, (int)coords.y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &pixelData);
|
|
return pixelData;
|
|
}
|
|
|
|
void FrameBuffer::SetDrawBuffer(GLenum draw)
|
|
{
|
|
Bind();
|
|
//glReadBuffer(draw);
|
|
Unbind();
|
|
}
|
|
|
|
void FrameBuffer::SetReadBuffer(GLenum read)
|
|
{
|
|
Bind();
|
|
//glReadBuffer(read);
|
|
Unbind();
|
|
}
|
|
}
|