Monday, November 20, 2017

opengl - FrameBuffer Render to texture not working all the way


I am learning to use Frame Buffer Objects. For this purpose, I chose to render a triangle to a texture and then map that to a quad.


When I render the triangle, I clear the color to something blue. So, when I render the texture on the quad from fbo, it only renders everything blue, but doesn't show up the triangle. I can't seem to figure out why this is happening. Can someone please help me out with this ?


I'll post the rendering code here, since glCheckFramebufferStatus doesn't complain when I setup the FBO. I've pasted the setup code at the end. Here is my rendering code:



void FrameBufferObject::Render(unsigned int elapsedGameTime)
{
glBindFramebuffer(GL_FRAMEBUFFER, m_FBO);
glClearColor(0.0, 0.6, 0.5, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// adjust viewport and projection matrices to texture dimensions
glPushAttrib(GL_VIEWPORT_BIT);
glViewport(0,0, m_FBOWidth, m_FBOHeight);


glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, m_FBOWidth, 0, m_FBOHeight, 1.0, 100.0);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

DrawTriangle();

glPopAttrib();

// setting FrameBuffer back to window-specified Framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, 0); //unbind

// back to normal viewport and projection matrix
//glViewport(0, 0, 1280, 768);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0, 1.33, 1.0, 1000.0);


glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

render(elapsedGameTime);
}




void FrameBufferObject::DrawTriangle()
{
glPushMatrix();

glBegin(GL_TRIANGLES);
glColor3f(1, 0, 0);

glVertex2d(0, 0);
glVertex2d(m_FBOWidth, 0);
glVertex2d(m_FBOWidth, m_FBOHeight);


glEnd();

glPopMatrix();
}



void FrameBufferObject::render(unsigned int elapsedTime)
{
glEnable(GL_TEXTURE_2D);

glBindTexture(GL_TEXTURE_2D, m_TextureID);

glPushMatrix();

glTranslated(0, 0, -20);

glBegin(GL_QUADS);
glColor4f(1, 1, 1, 1);

glTexCoord2f(1, 1); glVertex3f(1,1,1);

glTexCoord2f(0, 1); glVertex3f(-1,1,1);
glTexCoord2f(0, 0); glVertex3f(-1,-1,1);
glTexCoord2f(1, 0); glVertex3f(1,-1,1);

glEnd();
glPopMatrix();

glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);


}



void FrameBufferObject::Initialize()
{
// Generate FBO
glGenFramebuffers(1, &m_FBO);
glBindFramebuffer(GL_FRAMEBUFFER, m_FBO);

// Add depth buffer as a renderbuffer to fbo

// create depth buffer id

glGenRenderbuffers(1, &m_DepthBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, m_DepthBuffer);

// allocate space to render buffer for depth buffer
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, m_FBOWidth, m_FBOHeight);

// attaching renderBuffer to FBO
// attach depth buffer to FBO at depth_attachment

glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_DepthBuffer);

// Adding a texture to fbo
// Create a texture
glGenTextures(1, &m_TextureID);
glBindTexture(GL_TEXTURE_2D, m_TextureID);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_FBOWidth, m_FBOHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); // onlly allocating space
glBindTexture(GL_TEXTURE_2D, 0);

// attach texture to FBO
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_TextureID, 0);

// Check FBO Status
if( glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
std::cout << "\n Error:: FrameBufferObject::Initialize() :: FBO loading not complete \n";


// switch back to window system Framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}

Thanks!



Answer



Everything was fine. The triangle I was rendering for the FBO was getting clipped which is why I was not seeing anything. A translate Z of -20 is all it took to get the triangle rendering properly.


A (obvious) thing I learnt: When the user FBO is not working properly, render it to the normal framebuffer and see if what you expect to show up in the user FBO, actually shows up there. If not, you have a problem in the way you are rendering to the user FBO.


Hope it helps someone.


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...