From 84662d2c9f942da74465849d590f66874bc48268 Mon Sep 17 00:00:00 2001 From: Anselme Date: Thu, 3 Dec 2015 12:00:19 +0100 Subject: [PATCH] enhanced texture class, implemented framebuffer class, moved gbuffer in deferredmodule.cpp --- CMakeLists.txt | 1 - deferredmodule.cpp | 34 +++++++++++++++++++ deferredmodule.h | 11 +++++-- framebuffer.cpp | 32 +++++++++++++++++- framebuffer.h | 14 ++++++++ gbuffer.cpp | 56 -------------------------------- gbuffer.h | 26 --------------- image.h | 37 +++++++++++++++++++++ texture.cpp | 81 ++++++++++++++-------------------------------- texture.h | 18 ++++++++--- 10 files changed, 162 insertions(+), 148 deletions(-) delete mode 100644 gbuffer.cpp delete mode 100644 gbuffer.h diff --git a/CMakeLists.txt b/CMakeLists.txt index f5af1df..ce62805 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,7 +13,6 @@ endif(WIN32) set(LIB_SRC_LIST framebuffer.cpp - gbuffer.cpp meshbuilder.cpp phongentity.cpp phongmaterial.cpp diff --git a/deferredmodule.cpp b/deferredmodule.cpp index 2c1342a..22feb0e 100644 --- a/deferredmodule.cpp +++ b/deferredmodule.cpp @@ -1 +1,35 @@ #include "deferredmodule.h" +#include "glassert.h" +#include "texture.h" + +GBuffer::GBuffer(int width, int height) : FrameBuffer() +{ + Texture* tex; + // - Normal buffer + tex = new Texture(GL_RGB, GL_RGB16F, width, height, GL_FLOAT); + tex->setFiltering(GL_NEAREST); + addTexture(tex, GL_COLOR_ATTACHMENT0); + + // - Color + Specular exponent buffer + tex = new Texture(GL_RGBA, GL_RGBA, width, height); + tex->setFiltering(GL_NEAREST); + addTexture(tex, GL_COLOR_ATTACHMENT1); + + // - Specular color + objectId buffer + tex = new Texture(GL_RGBA, GL_RGBA, width, height); + tex->setFiltering(GL_NEAREST); + addTexture(tex, GL_COLOR_ATTACHMENT2); + + // - depth buffer + tex = new Texture(GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, width, height, GL_FLOAT); + tex->setFiltering(GL_NEAREST); + addTexture(tex, GL_DEPTH_ATTACHMENT); + + initGL(); +} + +GBuffer::~GBuffer() +{ + for(Texture* t : textures) + delete(t); +} diff --git a/deferredmodule.h b/deferredmodule.h index 183bd21..6e871e1 100644 --- a/deferredmodule.h +++ b/deferredmodule.h @@ -1,14 +1,19 @@ #ifndef DEFERREDMODULE_H #define DEFERREDMODULE_H +#include "framebuffer.h" #include "module.h" -#include -#include -#include class Shader; class PhongEntity; +class GBuffer : public FrameBuffer +{ +public: + GBuffer(int width, int height); + ~GBuffer(); +}; + class DeferredModule : public Module { public: diff --git a/framebuffer.cpp b/framebuffer.cpp index 286b43a..04bc564 100644 --- a/framebuffer.cpp +++ b/framebuffer.cpp @@ -1,7 +1,37 @@ #include "framebuffer.h" +#include "texture.h" +#include "glassert.h" FrameBuffer::FrameBuffer() { - + glAssert(glGenFramebuffers(1, &fbo)); } +FrameBuffer::~FrameBuffer() +{ + glAssert(glDeleteFramebuffers(1, &fbo)); +} + +void FrameBuffer::addTexture(Texture* tex, GLenum attachment) +{ + textures.push_back(tex); + bindFBO(); + glAssert(glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, tex->getTarget(), tex->getId(), 0)); + attachments.push_back(attachment); +} + +void FrameBuffer::initGL() +{ + bindFBO(); + glAssert(glDrawBuffers(attachments.size(), attachments.data())); +} + +void FrameBuffer::bindFBO() +{ + glAssert(glBindFramebuffer(GL_FRAMEBUFFER, fbo)); +} + +Texture* FrameBuffer::getTexture(int texId) +{ + return textures[texId]; +} diff --git a/framebuffer.h b/framebuffer.h index dea8cb6..f5b35da 100644 --- a/framebuffer.h +++ b/framebuffer.h @@ -1,11 +1,25 @@ #ifndef FRAMEBUFFER_H #define FRAMEBUFFER_H +#include +#include + +class Texture; class FrameBuffer { +protected: + GLuint fbo; + std::vector textures; + std::vector attachments; public: FrameBuffer(); + ~FrameBuffer(); + void addTexture(Texture* tex, GLenum attachment); + void initGL(); + + void bindFBO(); + Texture* getTexture(int texId); }; #endif // FRAMEBUFFER_H diff --git a/gbuffer.cpp b/gbuffer.cpp deleted file mode 100644 index 8a3bf0c..0000000 --- a/gbuffer.cpp +++ /dev/null @@ -1,56 +0,0 @@ -#include "gbuffer.h" -#include "sparrowrenderer.h" -#include "glassert.h" - -GBuffer::GBuffer(int width, int height) -{ - glAssert(glGenFramebuffers(1, &fbo)); - glAssert(glBindFramebuffer(GL_FRAMEBUFFER, fbo)); - - // - Normal buffer - glAssert(glGenTextures(1, textures + NORMAL)); - glAssert(glBindTexture(GL_TEXTURE_2D, textures[NORMAL])); - glAssert(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, width, height, 0, GL_RGB, GL_FLOAT, NULL)); - glAssert(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)); - glAssert(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)); - glAssert(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[NORMAL], 0)); - - // - Color + Specular exponent buffer - glAssert(glGenTextures(1, textures + COLOR)); - glAssert(glBindTexture(GL_TEXTURE_2D, textures[COLOR])); - glAssert(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL)); - glAssert(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)); - glAssert(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)); - glAssert(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, textures[COLOR], 0)); - - // - Specular color + objectId buffer - glAssert(glGenTextures(1, textures + SPECULAR)); - glAssert(glBindTexture(GL_TEXTURE_2D, textures[SPECULAR])); - glAssert(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL)); - glAssert(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)); - glAssert(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)); - glAssert(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, textures[SPECULAR], 0)); - - // - depth buffer - glAssert(glGenTextures(1, textures + DEPTH)); - glAssert(glBindTexture(GL_TEXTURE_2D, textures[DEPTH])); - glAssert(glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL)); - glAssert(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)); - glAssert(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)); - glAssert(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, textures[DEPTH], 0)); - - // - Tell OpenGL which color attachments we'll use (of this framebuffer) for rendering - GLuint attachments[4] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_DEPTH_ATTACHMENT}; - glAssert(glDrawBuffers(4, attachments)); -} - -void GBuffer::bind() -{ - glAssert(glBindFramebuffer(GL_FRAMEBUFFER, fbo)); -} - -void GBuffer::bindTexture(TextureType type, int slot) -{ - glAssert(glActiveTexture(GL_TEXTURE0 + slot)); - glAssert(glBindTexture(GL_TEXTURE_2D, textures[type])); -} diff --git a/gbuffer.h b/gbuffer.h deleted file mode 100644 index 137a808..0000000 --- a/gbuffer.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef GBUFFER_H -#define GBUFFER_H - -#include - -class GBuffer -{ - // fbo - GLuint fbo; - // textures - enum TextureType - { - NORMAL, - COLOR, - SPECULAR, - DEPTH, - NB_TEXTURES - }; - GLuint textures[NB_TEXTURES]; -public: - GBuffer(int width, int height); - void bind(); - void bindTexture(TextureType type, int slot); -}; - -#endif // GBUFFER_H diff --git a/image.h b/image.h index 790864d..6217065 100644 --- a/image.h +++ b/image.h @@ -2,6 +2,7 @@ #define IMAGE #include +#include struct Image { @@ -12,6 +13,42 @@ struct Image Image() : pixels(NULL) {} + Image(int myDepth, int myWidth, int myHeight, float frequency, float amplitude) : + width(myWidth), + height(myHeight), + depth(myDepth) + { + allocate(width * height * (depth/8)); + unsigned char* data = (unsigned char*)pixels; + + float xFactor = 1.0f / (width - 1); + float yFactor = 1.0f / (height - 1); + + for( int row = 0; row < height; row++ ) { + for( int col = 0 ; col < width; col++ ) { + float x = xFactor * col; + float y = yFactor * row; + float sum = 0.0f; + float freq = frequency; + float scale = amplitude; + + // Compute the sum for each octave + for( int oct = 0; oct < 4 ; oct++ ) { + glm::vec2 p(x * freq, y * freq); + float val = glm::perlin(p, glm::vec2(freq)) / scale; + sum += val; + float result = (sum + 1.0f)/ 2.0f; + + // Store in texture buffer + data[((row * width + col) * 4) + oct] = + (unsigned char) ( result * 255.0f ); + freq *= 2.0f; // Double the frequency + scale *= amplitude; // Next power of b + } + } + } + } + ~Image() { if(pixels != NULL) diff --git a/texture.cpp b/texture.cpp index a9c5226..f9bfc9b 100644 --- a/texture.cpp +++ b/texture.cpp @@ -1,37 +1,40 @@ #include "texture.h" #include "glassert.h" #include "image.h" -#include - -Texture::Texture() : type(GL_TEXTURE_2D) +Texture::Texture(GLenum format, + GLenum internal_format, + int width, + int height, + GLenum dataType, + GLenum texTarget) : + target(texTarget) { glAssert(glGenTextures(1, &texId)); - glAssert(glBindTexture(type, texId)); - createNoiseTexture(GL_TEXTURE_2D, 512, 512, 10, 1.5f); + glAssert(glBindTexture(target, texId)); + glAssert(glTexImage2D(target, 0, internal_format, width, height, 0, format, dataType, NULL)); setWrap(GL_REPEAT); setFiltering(GL_LINEAR); } -Texture::Texture(Image* myImage) : type(GL_TEXTURE_2D) +Texture::Texture(Image* myImage) : target(GL_TEXTURE_2D) { glAssert(glGenTextures(1, &texId)); - glAssert(glBindTexture(type, texId)); - - createTexture(myImage, GL_TEXTURE_2D); + glAssert(glBindTexture(target, texId)); + initPixels(myImage, GL_TEXTURE_2D); setWrap(GL_REPEAT); setFiltering(GL_LINEAR); } -Texture::Texture(Image* myCubemapImages[6]) : type(GL_TEXTURE_CUBE_MAP) +Texture::Texture(Image* myCubemapImages[6]) : target(GL_TEXTURE_CUBE_MAP) { glAssert(glActiveTexture(GL_TEXTURE0)); glAssert(glGenTextures(1, &texId)); - glAssert(glBindTexture(type, texId)); + glAssert(glBindTexture(target, texId)); for(int i=0; i<6; ++i) { - createTexture(myCubemapImages[i], GL_TEXTURE_CUBE_MAP_POSITIVE_X + i); + initPixels(myCubemapImages[i], GL_TEXTURE_CUBE_MAP_POSITIVE_X + i); setWrap(GL_CLAMP_TO_EDGE); setFiltering(GL_LINEAR); } @@ -42,73 +45,39 @@ Texture::~Texture() glAssert(glDeleteTextures(1, &texId)); } -void Texture::createNoiseTexture(GLenum textureSlot, int width, int height, float frequency, float amplitude) -{ - GLubyte *data = new GLubyte[ width * height * 4]; - - float xFactor = 1.0f / (width - 1); - float yFactor = 1.0f / (height - 1); - - for( int row = 0; row < height; row++ ) { - for( int col = 0 ; col < width; col++ ) { - float x = xFactor * col; - float y = yFactor * row; - float sum = 0.0f; - float freq = frequency; - float scale = amplitude; - - // Compute the sum for each octave - for( int oct = 0; oct < 4 ; oct++ ) { - glm::vec2 p(x * freq, y * freq); - float val = glm::perlin(p, glm::vec2(freq)) / scale; - sum += val; - float result = (sum + 1.0f)/ 2.0f; - - // Store in texture buffer - data[((row * width + col) * 4) + oct] = - (GLubyte) ( result * 255.0f ); - freq *= 2.0f; // Double the frequency - scale *= amplitude; // Next power of b - } - } - } - glAssert(glTexImage2D(textureSlot, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data)); -} - -void Texture::createTexture(Image* myImage, GLenum textureSlot) +void Texture::initPixels(Image* myImage, GLenum target) { switch(myImage->depth) { case 32: - glAssert(glTexImage2D(textureSlot, 0, GL_RGBA, myImage->width, myImage->height, 0, GL_BGRA, GL_UNSIGNED_BYTE, myImage->pixels)); + glAssert(glTexImage2D(target, 0, GL_RGBA, myImage->width, myImage->height, 0, GL_BGRA, GL_UNSIGNED_BYTE, myImage->pixels)); break; case 24: - glAssert(glTexImage2D(textureSlot, 0, GL_RGB, myImage->width, myImage->height, 0, GL_BGR, GL_UNSIGNED_BYTE, myImage->pixels)); + glAssert(glTexImage2D(target, 0, GL_RGB, myImage->width, myImage->height, 0, GL_BGR, GL_UNSIGNED_BYTE, myImage->pixels)); break; case 8: - glAssert(glTexImage2D(textureSlot, 0, GL_R8, myImage->width, myImage->height, 0, GL_RED, GL_UNSIGNED_BYTE, myImage->pixels)); + glAssert(glTexImage2D(target, 0, GL_R8, myImage->width, myImage->height, 0, GL_RED, GL_UNSIGNED_BYTE, myImage->pixels)); break; } - } void Texture::setWrap(GLint wrap) { - glAssert(glTexParameteri(type, GL_TEXTURE_WRAP_S, wrap)); - glAssert(glTexParameteri(type, GL_TEXTURE_WRAP_T, wrap)); - glAssert(glTexParameteri(type, GL_TEXTURE_WRAP_R, wrap)); + glAssert(glTexParameteri(target, GL_TEXTURE_WRAP_S, wrap)); + glAssert(glTexParameteri(target, GL_TEXTURE_WRAP_T, wrap)); + glAssert(glTexParameteri(target, GL_TEXTURE_WRAP_R, wrap)); } void Texture::setFiltering(GLint filter) { - glAssert(glTexParameteri(type, GL_TEXTURE_MIN_FILTER, filter)); - glAssert(glTexParameteri(type, GL_TEXTURE_MAG_FILTER, filter)); + glAssert(glTexParameteri(target, GL_TEXTURE_MIN_FILTER, filter)); + glAssert(glTexParameteri(target, GL_TEXTURE_MAG_FILTER, filter)); } void Texture::bind(int slot) { GLenum texSlot = GL_TEXTURE0+slot; glAssert(glActiveTexture(texSlot)); - glAssert(glBindTexture(type, texId)); + glAssert(glBindTexture(target, texId)); } diff --git a/texture.h b/texture.h index af720c6..94008c6 100644 --- a/texture.h +++ b/texture.h @@ -10,15 +10,19 @@ class Texture { private: GLuint texId; - GLenum type; + GLenum target; - void createNoiseTexture(GLenum textureSlot, int width, int height, float frequency, float myScale); - void createTexture(Image* myImage, GLenum textureSlot); - void setWrap(GLint wrap); - void setFiltering(GLint filter); + void initPixels(Image* myImage, GLenum textureSlot); public: // creates a 2D texture from perlin noise Texture(); + // creates an empty 2D texture + Texture(GLenum format = GL_RGBA, + GLenum internal_format = GL_RGBA, + int width = 512, + int height = 512, + GLenum dataType = GL_UNSIGNED_BYTE, + GLenum texTarget = GL_TEXTURE_2D); // creates a standard texture from an image Texture(Image* myImage); // creates a cubeMap from 6 images @@ -26,6 +30,10 @@ public: ~Texture(); void bind(int slot); + GLuint getId() {return texId;} + GLenum getTarget() {return target;} + void setWrap(GLint wrap); + void setFiltering(GLint filter); }; #endif // TEXTURE_H