Files
panopainter/engine/rtt.cpp

168 lines
4.1 KiB
C++

#include "pch.h"
#include "log.h"
#include "rtt.h"
RTT::RTT()
{
fboID = 0;
rboID = 0;
w = 0;
h = 0;
}
RTT::~RTT()
{
//destroy();
}
void RTT::destroy()
{
if (rboID)
{
glDeleteRenderbuffers(1, &rboID);
}
if (texID)
{
unbindTexture();
glDeleteTextures(1, &texID);
LOG("TEX rtt destroy %d", texID)
}
if (fboID)
{
unbindFramebuffer();
glDeleteFramebuffers(1, &fboID);
LOG("RTT DESTROY %d", fboID);
}
texID = 0;
fboID = 0;
rboID = 0;
// w = 0;
// h = 0;
}
bool RTT::create(int width, int height, int tex/* = -1*/)
{
// Destroy any previously created object
destroy();
w = width;
h = height;
if (tex == -1)
{
glGenTextures(1, &texID);
LOG("TEX rtt create %d", texID);
}
else
{
texID = tex;
}
glBindTexture(GL_TEXTURE_2D, texID);
if (tex == -1)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glBindTexture(GL_TEXTURE_2D, 0);
// Create a renderbuffer object to store depth info
// glGenRenderbuffers(1, &rboID);
// glBindRenderbuffer(GL_RENDERBUFFER, rboID);
// glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
// glBindRenderbuffer(GL_RENDERBUFFER, 0);
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldFboID);
// Create a framebuffer object
glGenFramebuffers(1, &fboID);
glBindFramebuffer(GL_FRAMEBUFFER, fboID);
LOG("RTT CREATE %d - tex %d", fboID, texID);
// Attach the texture to FBO color attachment point
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texID, 0);
// Attach the renderbuffer to depth attachment point
//glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboID);
auto err2str = [](GLenum err) {
switch (err)
{
case GL_FRAMEBUFFER_UNDEFINED: return "GL_FRAMEBUFFER_UNDEFINED";
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: return "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT";
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: return "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT";
case GL_FRAMEBUFFER_UNSUPPORTED: return "GL_FRAMEBUFFER_UNSUPPORTED";
case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: return "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE";
default: return "UNKNOWN";
}
};
// Check FBO status
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE)
LOG("RTT::create failed because: %s", err2str(status));
// Switch back to window-system-provided framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, oldFboID);
oldFboID = 0;
return status == GL_FRAMEBUFFER_COMPLETE;
}
void RTT::bindFramebuffer()
{
#ifdef DEBUG
if (bound)
{
LOG("framebuffer bound twice!");
#ifdef _WIN32
__debugbreak();
#endif
}
#endif // _DEBUG
bound = true;
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldFboID);
glBindFramebuffer(GL_FRAMEBUFFER, fboID);
}
void RTT::unbindFramebuffer()
{
glBindFramebuffer(GL_FRAMEBUFFER, oldFboID);
oldFboID = 0;
bound = false;
}
void RTT::clear(glm::vec4 color)
{
glClearColor(color.r, color.g, color.b, color.a);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
void RTT::readTextureData(uint8_t* buffer)
{
glReadBuffer(GL_BACK);
bindFramebuffer();
//glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer);
glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
unbindFramebuffer();
glReadBuffer(GL_NONE);
}
uint8_t* RTT::createBuffer()
{
return new uint8_t[w * h * 4];
}
void RTT::bindTexture()
{
glBindTexture(GL_TEXTURE_2D, texID);
}
void RTT::unbindTexture()
{
glBindTexture(GL_TEXTURE_2D, 0);
}