glfw/examples/ShadowMaps/source/DeferredRendering/FBORenderTexture.cpp
2017-09-22 11:01:51 +08:00

175 lines
6.4 KiB
C++

#include "FBORenderTexture.h"
#include <exception>
/**
* Create the FBO render texture initializing all the stuff that we need
*/
FBORenderTexture::FBORenderTexture(int _dWidth, int _dHeight)
{
// Save extensions
m_width = _dWidth;
m_height = _dHeight;
// Generate the OGL resources for what we need
glGenFramebuffersEXT(1, &m_fbo);
glGenRenderbuffersEXT(1, &m_diffuseRT);
glGenRenderbuffersEXT(1, &m_positionRT);
glGenRenderbuffersEXT(1, &m_normalsRT);
glGenRenderbuffersEXT(1, &m_depthBuffer);
// Bind the FBO so that the next operations will be bound to it
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
// Bind the diffuse render target
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_diffuseRT);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA, m_width, m_height);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, m_diffuseRT);
// Bind the position render target
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_positionRT);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA32F_ARB, m_width, m_height);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_RENDERBUFFER_EXT, m_positionRT);
// Bind the normal render target
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_normalsRT);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA16F_ARB, m_width, m_height);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT2_EXT, GL_RENDERBUFFER_EXT, m_normalsRT);
// Bind the depth buffer
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_depthBuffer);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, m_width, m_height);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_depthBuffer);
// Generate and bind the OGL texture for diffuse
glGenTextures(1, &m_diffuseTexture);
glBindTexture(GL_TEXTURE_2D, m_diffuseTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// Attach the texture to the FBO
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_diffuseTexture, 0);
// Generate and bind the OGL texture for positions
glGenTextures(1, &m_positionTexture);
glBindTexture(GL_TEXTURE_2D, m_positionTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F_ARB, m_width, m_height, 0, GL_RGBA, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// Attach the texture to the FBO
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, m_positionTexture, 0);
// Generate and bind the OGL texture for normals
glGenTextures(1, &m_normalsTexture);
glBindTexture(GL_TEXTURE_2D, m_normalsTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, m_width, m_height, 0, GL_RGBA, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// Attach the texture to the FBO
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT2_EXT, GL_TEXTURE_2D, m_normalsTexture, 0);
// Check if all worked fine and unbind the FBO
GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
if( status != GL_FRAMEBUFFER_COMPLETE_EXT)
throw new std::exception("Can't initialize an FBO render texture. FBO initialization failed.");
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}
/**
* Destructor
*/
FBORenderTexture::~FBORenderTexture(){
glDeleteTextures(1, &m_normalsTexture);
glDeleteTextures(1, &m_positionTexture);
glDeleteTextures(1, &m_diffuseTexture);
glDeleteFramebuffersEXT(1, &m_fbo);
glDeleteRenderbuffersEXT(1, &m_diffuseRT);
glDeleteRenderbuffersEXT(1, &m_positionRT);
glDeleteRenderbuffersEXT(1, &m_normalsRT);
glDeleteRenderbuffersEXT(1, &m_depthBuffer);
}
/**
* Start rendering to the texture
* Both color and depth buffers are cleared.
*/
void FBORenderTexture::start(){
// Bind our FBO and set the viewport to the proper size
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
glPushAttrib(GL_VIEWPORT_BIT);
glViewport(0,0,m_width, m_height);
// Clear the render targets
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
glActiveTextureARB(GL_TEXTURE0_ARB);
glEnable(GL_TEXTURE_2D);
// Specify what to render an start acquiring
GLenum buffers[] = { GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_COLOR_ATTACHMENT2_EXT };
glDrawBuffers(3, buffers);
}
/**
* Stop rendering to this texture.
*/
void FBORenderTexture::stop(){
// Stop acquiring and unbind the FBO
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glPopAttrib();
}
/**
* Show the texture to screen. It is just for debug purposes.
*/
void FBORenderTexture::showTexture(unsigned int i, float fWindowsWidth, float fWindowsHeight, float fSizeX, float fSizeY, float x, float y) const {
GLuint texture = m_diffuseTexture;
if(i == 1) texture = m_positionTexture;
else
if(i == 2) texture = m_normalsTexture;
//Projection setup
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0,fWindowsWidth,0,fWindowsHeight,0.1f,2);
//Model setup
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glActiveTextureARB(GL_TEXTURE0_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture);
// Render the quad
glLoadIdentity();
glTranslatef(x,fWindowsHeight - y - fSizeY,-1.0);
glColor3f(1,1,1);
glBegin(GL_QUADS);
glTexCoord2f( 0, 1 );
glVertex3f( 0.0f, (float) fSizeY, 0.0f);
glTexCoord2f( 0, 0 );
glVertex3f( 0.0f, 0.0f, 0.0f);
glTexCoord2f( 1, 0 );
glVertex3f( fSizeX, 0.0f, 0.0f);
glTexCoord2f( 1, 1 );
glVertex3f( fSizeX, (float) fSizeY, 0.0f);
glEnd();
glBindTexture(GL_TEXTURE_2D, 0);
//Reset to the matrices
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
}