#include #include "Framebuffer.h" #include "client/Utils.h" Framebuffer::Framebuffer(u32 width, u32 height, u32 mode) : mode(mode), buffer(0), valid(false) { glGenFramebuffers(1, &buffer); glBindFramebuffer(GL_FRAMEBUFFER, buffer); GLuint attachments[4]; u32 counter = 0; if(mode & POSITION) // position texture { glGenTextures(1, &(textures[0])); glBindTexture(GL_TEXTURE_2D, textures[0]); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, width, height, 0, GL_RGB, GL_FLOAT, 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); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + counter, GL_TEXTURE_2D, textures[0], 0); attachments[counter] = GL_COLOR_ATTACHMENT0 + counter; counter++; } if(mode & NORMAL) // normal texture { glGenTextures(1, &(textures[1])); glBindTexture(GL_TEXTURE_2D, textures[1]); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, width, height, 0, GL_RGB, GL_FLOAT, 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); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + counter, GL_TEXTURE_2D, textures[1], 0); attachments[counter] = GL_COLOR_ATTACHMENT0 + counter; counter++; } if(mode & COLOR) // color texture { glGenTextures(1, &(textures[2])); glBindTexture(GL_TEXTURE_2D, textures[2]); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 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); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + counter, GL_TEXTURE_2D, textures[2], 0); attachments[counter] = GL_COLOR_ATTACHMENT0 + counter; counter++; } if(mode & RED) // single color channel texture { glGenTextures(1, &textures[3]); glBindTexture(GL_TEXTURE_2D, textures[3]); glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, width, height, 0, GL_RGB, GL_FLOAT, 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); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + counter, GL_TEXTURE_2D, textures[3], 0); attachments[counter] = GL_COLOR_ATTACHMENT0 + counter; counter++; } if(mode & DEPTH24_STENCIL8) // depth texture { glGenTextures(1, &textures[4]); glBindTexture(GL_TEXTURE_2D, textures[4]); glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_STENCIL, width, height, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, 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); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, textures[4], 0); } glDrawBuffers(counter, attachments); if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { std::cout << "frame buffer is not complete\n"; return; } valid = true; } Framebuffer::~Framebuffer() { glDeleteFramebuffers(1, &buffer); for(GLuint& texture : textures) { glDeleteTextures(1, &texture); } } bool Framebuffer::isValid() const { return valid; } void Framebuffer::bind() const { glBindFramebuffer(GL_FRAMEBUFFER, buffer); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } void Framebuffer::resize(u32 width, u32 height) const { if(mode & POSITION) // position texture { glBindTexture(GL_TEXTURE_2D, textures[0]); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, width, height, 0, GL_RGB, GL_FLOAT, nullptr); } if(mode & NORMAL) // normal texture { glBindTexture(GL_TEXTURE_2D, textures[1]); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, width, height, 0, GL_RGB, GL_FLOAT, nullptr); } if(mode & COLOR) // color texture { glBindTexture(GL_TEXTURE_2D, textures[2]); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); } if(mode & RED) // single color channel texture { glBindTexture(GL_TEXTURE_2D, textures[3]); glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width, height, 0, GL_RGB, GL_FLOAT, nullptr); } if(mode & DEPTH24_STENCIL8) // depth texture { glBindTexture(GL_TEXTURE_2D, textures[4]); glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, width, height, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, nullptr); } } void Framebuffer::bindPositionTexture(u32 textureUnit) const { glActiveTexture(GL_TEXTURE0 + textureUnit); glBindTexture(GL_TEXTURE_2D, textures[0]); } void Framebuffer::bindNormalTexture(u32 textureUnit) const { glActiveTexture(GL_TEXTURE0 + textureUnit); glBindTexture(GL_TEXTURE_2D, textures[1]); } void Framebuffer::bindColorTexture(u32 textureUnit) const { glActiveTexture(GL_TEXTURE0 + textureUnit); glBindTexture(GL_TEXTURE_2D, textures[2]); } void Framebuffer::bindRedTexture(u32 textureUnit) const { glActiveTexture(GL_TEXTURE0 + textureUnit); glBindTexture(GL_TEXTURE_2D, textures[3]); } void Framebuffer::bindDepthTexture(u32 textureUnit) const { glActiveTexture(GL_TEXTURE0 + textureUnit); glBindTexture(GL_TEXTURE_2D, textures[4]); }