#include #include "client/rendering/wrapper/Framebuffer.h" Framebuffer::Framebuffer(const WindowSize& size, uint mode, bool texCompare) : mode(mode), textures(0), buffer(0), error(false) { glGenFramebuffers(1, &buffer); glBindFramebuffer(GL_FRAMEBUFFER, buffer); data[0] = {POSITION, GL_RGB16F, GL_RGB, GL_FLOAT}; data[1] = {NORMAL, GL_RGB16F, GL_RGB, GL_FLOAT}; data[2] = {COLOR, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE}; data[3] = {RED, GL_R32F, GL_RGB, GL_FLOAT}; data[4] = {TANGENT, GL_RGB16F, GL_RGB, GL_FLOAT}; data[5] = {DEPTH, GL_DEPTH_COMPONENT32, GL_DEPTH_COMPONENT, GL_FLOAT}; GLuint attachments[5]; uint counter = 0; for(uint i = 0; i < 5; i++) { if(mode & data[i].mask) { setupTexture(i, size.width, size.height, attachments, counter); } } if(mode & DEPTH) { genTexture(5, size.width, size.height); if(texCompare) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); } glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, textures[5], 0); } glDrawBuffers(counter, attachments); GLenum glError = glCheckFramebufferStatus(GL_FRAMEBUFFER); if(glError != GL_FRAMEBUFFER_COMPLETE) { std::cout << "frame buffer error: " << getErrorString(error) << "\n"; error = true; } } Framebuffer::~Framebuffer() { glDeleteFramebuffers(1, &buffer); for(GLuint& texture : textures) { glDeleteTextures(1, &texture); } } bool Framebuffer::hasError() const { return error; } void Framebuffer::bind() const { glBindFramebuffer(GL_FRAMEBUFFER, buffer); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } void Framebuffer::resize(uint width, uint height) const { for(uint i = 0; i < 6; i++) { if(mode & data[i].mask) { glBindTexture(GL_TEXTURE_2D, textures[i]); glTexImage2D(GL_TEXTURE_2D, 0, data[i].internalFormat, width, height, 0, data[i].format, data[i].type, nullptr); } } } void Framebuffer::bindTexture(uint textureUnit, GLuint texture) const { glActiveTexture(GL_TEXTURE0 + textureUnit); glBindTexture(GL_TEXTURE_2D, texture); } void Framebuffer::bindPositionTexture(uint textureUnit) const { bindTexture(textureUnit, textures[0]); } void Framebuffer::bindNormalTexture(uint textureUnit) const { bindTexture(textureUnit, textures[1]); } void Framebuffer::bindColorTexture(uint textureUnit) const { bindTexture(textureUnit, textures[2]); } void Framebuffer::bindRedTexture(uint textureUnit) const { bindTexture(textureUnit, textures[3]); } void Framebuffer::bindTangentTexture(uint textureUnit) const { bindTexture(textureUnit, textures[4]); } void Framebuffer::bindDepthTexture(uint textureUnit) const { bindTexture(textureUnit, textures[5]); } void Framebuffer::genTexture(uint index, uint width, uint height) { glGenTextures(1, textures + index); glBindTexture(GL_TEXTURE_2D, textures[index]); glTexImage2D(GL_TEXTURE_2D, 0, data[index].internalFormat, width, height, 0, data[index].format, data[index].type, nullptr); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } void Framebuffer::setupTexture(uint index, uint width, uint height, GLuint* attachments, uint& counter) { genTexture(index, width, height); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + counter, GL_TEXTURE_2D, textures[index], 0); attachments[counter] = GL_COLOR_ATTACHMENT0 + counter; counter++; } const char* Framebuffer::getErrorString(GLenum error) const { switch(error) { 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_INCOMPLETE_DRAW_BUFFER: return "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER"; case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: return "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER"; case GL_FRAMEBUFFER_UNSUPPORTED: return "GL_FRAMEBUFFER_UNSUPPORTED"; case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: return "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE"; case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS: return "GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS"; } return "unknown error"; }