mirror of
https://github.com/glfw/glfw.git
synced 2025-10-05 06:06:36 +00:00
175 lines
6.4 KiB
C++
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();
|
|
} |