Skip to main content
GameDev.net gamedev.net
🔒 Locked 🎮 Unity

Seriously don't understand WHY my framebuffer isn't rendering as a texture

Started by Lil_Lloyd Jul 11, 2012 at 3:48 AM 23 replies 14.2k views
Original Post
Lil_Lloyd
Lil_Lloyd
Ok so I've looked at several tutorials and checked my code but something VERY simple must be eluding me here. I render a rotating teapot to a texture and then try and render this texture as a full screen quad, just to get used to framebuffers before doing anything fancy with them.

I have tested rendering the teapot straight to the screen, that was ok. I has tested my quad shading code by making the screen yellow in a fragment shader, that was ok too. However when trying to render to the texture I just don't get the results I want! I get NOTHING!

I have a framebuffer struct, and a helper function to set up a FBO as required:


typedef struct
{
GLubyte * imageData;
GLuint bpp;
GLuint width;
GLuint height;
GLuint texID;
GLuint type;
} Texture;

typedef struct
{
GLuint handle;
GLuint depthBuffer;
GLint depthHeight;
GLint depthWidth;
Texture textureData;
Texture nonTexture;
}FBO;

void FrameBufferObject(FBO& fboData,GLenum minFilter,GLenum magFilter)
{
glGenFramebuffers(1,&fboData.handle);
glBindFramebuffer(GL_FRAMEBUFFER,fboData.handle);

glGenTextures(1,&fboData.textureData.texID);
glBindTexture(GL_TEXTURE_2D,fboData.textureData.texID);
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,fboData.depthWidth,fboData.depthHeight,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);

glGenRenderbuffers(1,&fboData.depthBuffer);
glBindRenderbuffer(GL_RENDERBUFFER,fboData.depthBuffer);
glRenderbufferStorage(GL_RENDERBUFFER,GL_DEPTH_COMPONENT,fboData.depthWidth,fboData.depthHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,GL_RENDERBUFFER,fboData.depthBuffer);

glFramebufferTexture(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,fboData.textureData.texID,0);
GLenum drawBufs[] = {GL_COLOR_ATTACHMENT0};
glDrawBuffers(1,drawBufs);

if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
std::cout<<"problem with framebuffer!";
else
std::cout<<"framebuffer ok! <img src='http://public.gamedev.net//public/style_emoticons/<#EMO_DIR#>/smile.png' class='bbc_emoticon' alt=':)' />";

glBindFramebuffer(GL_FRAMEBUFFER,0);
}




my shader code is as follows:

//texture.vp
#version 330
in vec3 position;

out vec2 UV;

void main()
{
gl_Position = vec4(position,1);
UV = (position.xy+vec2(1,1))/2.0;
}

//texture.fp
#version 330

in vec2 UV;

out vec3 color;

uniform sampler2D renderedTexture;

void main()
{
color = texture(renderedTexture,UV).rgb;
}



I call my rendering code as follows...


void RenderToTexture()
{
glClear(GL_COLOR_BUFFER_BIT |GL_DEPTH_BUFFER_BIT );
glUseProgram(renderProgram);
glUniformMatrix4fv(MVPMatrixUniform,1,GL_FALSE,&MVPMatrix[0][0]);

glEnableVertexAttribArray(0);

//set variables for the fbo
glBindFramebuffer(GL_FRAMEBUFFER,frameBuf.handle);
glViewport(0,0,512,512);

GLenum drawBufs[] = {GL_COLOR_ATTACHMENT0};
glDrawBuffers(1,drawBufs);
teapot->render();
glUseProgram(0);
glDisableVertexAttribArray(0);
glBindFramebuffer(GL_FRAMEBUFFER,0);
}

void DrawTextureToQuad()
{
glClear(GL_COLOR_BUFFER_BIT |GL_DEPTH_BUFFER_BIT );
glViewport(0,0,640,480);

glUseProgram(textureProgram);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D,frameBuf.textureData.texID);

GLuint texID = glGetUniformLocation(textureProgram, "renderedTexture");
glUniform1i(texID,0);
glEnableVertexAttribArray(0);


//Render to the screen
glBindBuffer(GL_ARRAY_BUFFER, quad_vertexbuffer);
glVertexAttribPointer(
0, // attribute 0. No particular reason for 0, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// Draw the triangle !
glDrawArrays(GL_TRIANGLES, 0, 6); // From index 0 to 3 -> 1 triangle

glDisableVertexAttribArray(0);
glUseProgram(0);
}

void DrawGLScene(GLvoid)
{
MVPMatrix = perspMatrix * camMatrix * transformMatrix;
Update();
RenderToTexture();
DrawTextureToQuad();

glutSwapBuffers();
glutPostRedisplay();
}


If anyone can help, I'd be really grateful!
dpadam450
dpadam450
Can you load a different texture first and verify that the shader will texture it properly, you said you try all yellow but do you try using a texture thats not the framebuffer. Everything else looks fine.
NBA2K, Madden, Maneater, Killing Floor, Sims 
Lil_Lloyd
Lil_Lloyd
Hey, thanks. Yeah I was easily able to render another texture to the screen. I really don't know what I'm doing wrong....
dpadam450
dpadam450
So when you did the textured quad test, you also were drawing to the FBO?
NBA2K, Madden, Maneater, Killing Floor, Sims 
dpadam450
dpadam450
Only thing I saw different from my code was
glFramebufferTexture vs glFramebufferTexture2D is what I use.
NBA2K, Madden, Maneater, Killing Floor, Sims 
Lil_Lloyd
Lil_Lloyd
Thanks again. I tried changing it to glFrambufferTexture2D and even tried changing some flags from GL_FRAMEBUFFER to GL_DRAW_FRAMEBUFFER in desperate hacking but no luck at all. I really don't understand what's up
dpadam450
dpadam450
If you can use immediate mode, I would take away everything other than making an FBO and drawing a triangle to the FBO and then drawing another triangle with the FBO applied. Get rid of shaders and everything. Sometimes you just gotta rewrite things and also get rid of unrelated code.
NBA2K, Madden, Maneater, Killing Floor, Sims 
slicer4ever
slicer4ever
You need to unbind the texture that is for the framebuffer, before you bind the framebuffer. As far as i see atm(on phone), ur never unbinding the texture that the framebuffer uses.
Yours3&#33;f
Yours3&#33;f
hi,

here's a tiny little program that does fbos, hope this will help you. (The result you should see is a white triangle)


#include <iostream>

#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#undef near
#undef far
#endif

#include "GL/glew.h" //the mighty GLEW <img src='http://public.gamedev.net//public/style_emoticons/<#EMO_DIR#>/smile.png' class='bbc_emoticon' alt=':)' />
#include "SFML/Window.hpp"

/*
* Global variables
*/

sf::Window the_window;
sf::Event the_event;

float fps = 1.0f;
int frames = 0;
sf::Clock the_clock;
std::string app_path;
#define SCREEN_WIDTH 800
#define SCREEN_HEIGHT 600

GLuint tex;

GLuint fbo;

/*
* Function declarations
*/

void get_opengl_error( bool ignore = false );

void draw_quad()
{
glBegin( GL_QUADS );
glTexCoord2f( 0, 0 );
glVertex2f( 0, 0 );
glTexCoord2f( 1, 0 );
glVertex2f( 1, 0 );
glTexCoord2f( 1, 1 );
glVertex2f( 1, 1 );
glTexCoord2f( 0, 1 );
glVertex2f( 0, 1 );
glEnd();
}

void check_fbo()
{
if( glCheckFramebufferStatus( GL_FRAMEBUFFER ) != GL_FRAMEBUFFER_COMPLETE )
{
std::cerr << "FBO not complete.\n";
the_window.close();
exit( 1 );
}
}


int main( int argc, char* args[] )
{
/*
* Initialize OpenGL context
*/

the_window.create( sf::VideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, 32 ), "FBO", sf::Style::Default );

if( !the_window.isOpen() )
{
std::cerr << "Couldn't initialize SFML.\n";
the_window.close();
exit( 1 );
}

GLenum glew_error = glewInit();

if( glew_error != GLEW_OK )
{
std::cerr << "Error initializing GLEW: " << glewGetErrorString( glew_error ) << "\n";
the_window.close();
exit( 1 );
}

if( !GLEW_VERSION_3_3 )
{
std::cerr << "Error: OpenGL 3.3 is required\n";
the_window.close();
exit( 1 );
}

/*
* Initialize and load textures
*/

glEnable( GL_TEXTURE_2D );

glGenTextures( 1, &tex );
glBindTexture( GL_TEXTURE_2D, tex );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, SCREEN_WIDTH, SCREEN_HEIGHT, 0, GL_RGBA, GL_FLOAT, 0 );

get_opengl_error();

/*
* Initialize FBOs
*/

GLenum modes[] = { GL_COLOR_ATTACHMENT0 };

glGenFramebuffers( 1, &fbo );
glBindFramebuffer( GL_FRAMEBUFFER, fbo );
glDrawBuffers( 1, modes );
glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0 );

check_fbo();

glBindFramebuffer( GL_FRAMEBUFFER, 0 );

glBindTexture( GL_TEXTURE_2D, 0 );

get_opengl_error();


/*
* Set up matrices
*/

glViewport( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT );
glMatrixMode( GL_PROJECTION );
//x_min:0, x_max:1, y_min:0, y_max:1, z_min:0, z_max:-1
float ortho_matrix[] = { 2, 0, 0, 0,
0, 2, 0, 0,
0, 0, 2, 0,
-1, -1, -1, 1
};
glLoadMatrixf( ortho_matrix );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();

get_opengl_error();

/*
* Generate input
*/

glBindFramebuffer( GL_FRAMEBUFFER, fbo );

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

glPushMatrix();
glTranslatef( 0.5f, 0.5f, 0.0f );
glBegin( GL_TRIANGLES );
glColor3f( 1, 1, 1 );
glVertex2f( -0.25f, -0.25f );
glVertex2f( 0, 0.25f );
glVertex2f( 0.25f, -0.25f );
glEnd();
glPopMatrix();

glBindFramebuffer( GL_FRAMEBUFFER, 0 );

get_opengl_error();

/*
* MAIN LOOP
*/

the_clock.restart();

glEnable( GL_TEXTURE_2D );

glActiveTexture( GL_TEXTURE0 );
glBindTexture( GL_TEXTURE_2D, tex );

while( true )
{
/*
* Handle events
*/

while( the_window.pollEvent( the_event ) )
{
if( the_event.type == sf::Event::Closed )
{
the_window.close();
exit( 0 );
}
}

/*
* DRAW RESULT
*/

draw_quad();

/*
* Show the result
*/

the_window.display();

frames++;

if( the_clock.getElapsedTime().asMilliseconds() > 1000.0f )
{
int timepassed = the_clock.getElapsedTime().asMilliseconds();
fps = 1000.0f / ( ( float ) timepassed / ( float ) frames );
std::cout << "FPS: " << fps << " Time: " << ( float ) timepassed / ( float ) frames << "\n";
frames = 0;
timepassed = 0;
the_clock.restart();
}
}

return 0;
}

void get_opengl_error( bool ignore )
{
bool got_error = false;
GLenum error = 0;
error = glGetError();
std::string errorstring = "";

while( error != GL_NO_ERROR )
{
if( error == GL_INVALID_ENUM )
{
//An unacceptable value is specified for an enumerated argument. The offending command is ignored and has no other side effect than to set the error flag.
errorstring += "OpenGL error: invalid enum...\n";
got_error = true;
}

if( error == GL_INVALID_VALUE )
{
//A numeric argument is out of range. The offending command is ignored and has no other side effect than to set the error flag.
errorstring += "OpenGL error: invalid value...\n";
got_error = true;
}

if( error == GL_INVALID_OPERATION )
{
//The specified operation is not allowed in the current state. The offending command is ignored and has no other side effect than to set the error flag.
errorstring += "OpenGL error: invalid operation...\n";
got_error = true;
}

if( error == GL_STACK_OVERFLOW )
{
//This command would cause a stack overflow. The offending command is ignored and has no other side effect than to set the error flag.
errorstring += "OpenGL error: stack overflow...\n";
got_error = true;
}

if( error == GL_STACK_UNDERFLOW )
{
//This command would cause a stack underflow. The offending command is ignored and has no other side effect than to set the error flag.
errorstring += "OpenGL error: stack underflow...\n";
got_error = true;
}

if( error == GL_OUT_OF_MEMORY )
{
//There is not enough memory left to execute the command. The state of the GL is undefined, except for the state of the error flags, after this error is recorded.
errorstring += "OpenGL error: out of memory...\n";
got_error = true;
}

if( error == GL_TABLE_TOO_LARGE )
{
//The specified table exceeds the implementation's maximum supported table size. The offending command is ignored and has no other side effect than to set the error flag.
errorstring += "OpenGL error: table too large...\n";
got_error = true;
}

error = glGetError();
}

if( got_error && !ignore )
{
std::cerr << errorstring;
the_window.close();
return;
}
}


Lil_Lloyd
Lil_Lloyd

You need to unbind the texture that is for the framebuffer, before you bind the framebuffer. As far as i see atm(on phone), ur never unbinding the texture that the framebuffer uses.


I tried that in a session last night, but still no luck....

Thanks though! ;)
Lil_Lloyd
Lil_Lloyd

hi,

here's a tiny little program that does fbos, hope this will help you. (The result you should see is a white triangle)


#include <iostream>

#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#undef near
#undef far
#endif

#include "GL/glew.h" //the mighty GLEW <img src='http://public.gamedev.net//public/style_emoticons/<#EMO_DIR#>/smile.png' class='bbc_emoticon' alt=':)' />
#include "SFML/Window.hpp"

/*
* Global variables
*/

sf::Window the_window;
sf::Event the_event;

float fps = 1.0f;
int frames = 0;
sf::Clock the_clock;
std::string app_path;
#define SCREEN_WIDTH 800
#define SCREEN_HEIGHT 600

GLuint tex;

GLuint fbo;

/*
* Function declarations
*/

void get_opengl_error( bool ignore = false );

void draw_quad()
{
glBegin( GL_QUADS );
glTexCoord2f( 0, 0 );
glVertex2f( 0, 0 );
glTexCoord2f( 1, 0 );
glVertex2f( 1, 0 );
glTexCoord2f( 1, 1 );
glVertex2f( 1, 1 );
glTexCoord2f( 0, 1 );
glVertex2f( 0, 1 );
glEnd();
}

void check_fbo()
{
if( glCheckFramebufferStatus( GL_FRAMEBUFFER ) != GL_FRAMEBUFFER_COMPLETE )
{
std::cerr << "FBO not complete.\n";
the_window.close();
exit( 1 );
}
}


int main( int argc, char* args[] )
{
/*
* Initialize OpenGL context
*/

the_window.create( sf::VideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, 32 ), "FBO", sf::Style::Default );

if( !the_window.isOpen() )
{
std::cerr << "Couldn't initialize SFML.\n";
the_window.close();
exit( 1 );
}

GLenum glew_error = glewInit();

if( glew_error != GLEW_OK )
{
std::cerr << "Error initializing GLEW: " << glewGetErrorString( glew_error ) << "\n";
the_window.close();
exit( 1 );
}

if( !GLEW_VERSION_3_3 )
{
std::cerr << "Error: OpenGL 3.3 is required\n";
the_window.close();
exit( 1 );
}

/*
* Initialize and load textures
*/

glEnable( GL_TEXTURE_2D );

glGenTextures( 1, &tex );
glBindTexture( GL_TEXTURE_2D, tex );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, SCREEN_WIDTH, SCREEN_HEIGHT, 0, GL_RGBA, GL_FLOAT, 0 );

get_opengl_error();

/*
* Initialize FBOs
*/

GLenum modes[] = { GL_COLOR_ATTACHMENT0 };

glGenFramebuffers( 1, &fbo );
glBindFramebuffer( GL_FRAMEBUFFER, fbo );
glDrawBuffers( 1, modes );
glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0 );

check_fbo();

glBindFramebuffer( GL_FRAMEBUFFER, 0 );

glBindTexture( GL_TEXTURE_2D, 0 );

get_opengl_error();


/*
* Set up matrices
*/

glViewport( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT );
glMatrixMode( GL_PROJECTION );
//x_min:0, x_max:1, y_min:0, y_max:1, z_min:0, z_max:-1
float ortho_matrix[] = { 2, 0, 0, 0,
0, 2, 0, 0,
0, 0, 2, 0,
-1, -1, -1, 1
};
glLoadMatrixf( ortho_matrix );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();

get_opengl_error();

/*
* Generate input
*/

glBindFramebuffer( GL_FRAMEBUFFER, fbo );

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

glPushMatrix();
glTranslatef( 0.5f, 0.5f, 0.0f );
glBegin( GL_TRIANGLES );
glColor3f( 1, 1, 1 );
glVertex2f( -0.25f, -0.25f );
glVertex2f( 0, 0.25f );
glVertex2f( 0.25f, -0.25f );
glEnd();
glPopMatrix();

glBindFramebuffer( GL_FRAMEBUFFER, 0 );

get_opengl_error();

/*
* MAIN LOOP
*/

the_clock.restart();

glEnable( GL_TEXTURE_2D );

glActiveTexture( GL_TEXTURE0 );
glBindTexture( GL_TEXTURE_2D, tex );

while( true )
{
/*
* Handle events
*/

while( the_window.pollEvent( the_event ) )
{
if( the_event.type == sf::Event::Closed )
{
the_window.close();
exit( 0 );
}
}

/*
* DRAW RESULT
*/

draw_quad();

/*
* Show the result
*/

the_window.display();

frames++;

if( the_clock.getElapsedTime().asMilliseconds() > 1000.0f )
{
int timepassed = the_clock.getElapsedTime().asMilliseconds();
fps = 1000.0f / ( ( float ) timepassed / ( float ) frames );
std::cout << "FPS: " << fps << " Time: " << ( float ) timepassed / ( float ) frames << "\n";
frames = 0;
timepassed = 0;
the_clock.restart();
}
}

return 0;
}

void get_opengl_error( bool ignore )
{
bool got_error = false;
GLenum error = 0;
error = glGetError();
std::string errorstring = "";

while( error != GL_NO_ERROR )
{
if( error == GL_INVALID_ENUM )
{
//An unacceptable value is specified for an enumerated argument. The offending command is ignored and has no other side effect than to set the error flag.
errorstring += "OpenGL error: invalid enum...\n";
got_error = true;
}

if( error == GL_INVALID_VALUE )
{
//A numeric argument is out of range. The offending command is ignored and has no other side effect than to set the error flag.
errorstring += "OpenGL error: invalid value...\n";
got_error = true;
}

if( error == GL_INVALID_OPERATION )
{
//The specified operation is not allowed in the current state. The offending command is ignored and has no other side effect than to set the error flag.
errorstring += "OpenGL error: invalid operation...\n";
got_error = true;
}

if( error == GL_STACK_OVERFLOW )
{
//This command would cause a stack overflow. The offending command is ignored and has no other side effect than to set the error flag.
errorstring += "OpenGL error: stack overflow...\n";
got_error = true;
}

if( error == GL_STACK_UNDERFLOW )
{
//This command would cause a stack underflow. The offending command is ignored and has no other side effect than to set the error flag.
errorstring += "OpenGL error: stack underflow...\n";
got_error = true;
}

if( error == GL_OUT_OF_MEMORY )
{
//There is not enough memory left to execute the command. The state of the GL is undefined, except for the state of the error flags, after this error is recorded.
errorstring += "OpenGL error: out of memory...\n";
got_error = true;
}

if( error == GL_TABLE_TOO_LARGE )
{
//The specified table exceeds the implementation's maximum supported table size. The offending command is ignored and has no other side effect than to set the error flag.
errorstring += "OpenGL error: table too large...\n";
got_error = true;
}

error = glGetError();
}

if( got_error && !ignore )
{
std::cerr << errorstring;
the_window.close();
return;
}
}





Thankyou! I'll try dloading SFML and giving it a bash. Respect!
Lil_Lloyd
Lil_Lloyd
One thing is, I really need to get something working with shaders, in the long run it is obviously more flexible for me to do so and immediate mode is deprecated anyway. I'll keep trying!
Lil_Lloyd
Lil_Lloyd
So as a further note, is there a debug tool available that can check the contents of textures/video memory? I'm not sure if there is a problem with rendering to a texture or something happening to the texture (somehow) between the render to the framebuffer and the render to the full screen quad
Yours3&#33;f
Yours3&#33;f

So as a further note, is there a debug tool available that can check the contents of textures/video memory? I'm not sure if there is a problem with rendering to a texture or something happening to the texture (somehow) between the render to the framebuffer and the render to the full screen quad

google: gDEBugger
Yours3&#33;f
Yours3&#33;f

One thing is, I really need to get something working with shaders, in the long run it is obviously more flexible for me to do so and immediate mode is deprecated anyway. I'll keep trying!

ok, it shouldn't be much harder than immediate mode, in fact I myself use fbos with shaders. Just make sure your fbo setup is correct (see my little example) then set up your shaders (load them, bind attributes, uniforms, frag data locations, pass uniforms) then proceed with rendering as usual. Then you just have to display the result (the texture). You can check with gDEBugger if you do render to the texture successfully, and if you do then maybe you are not rendering the result correctly. Or the other way round.
Lil_Lloyd
Lil_Lloyd
gDebugger is realllllly awesome thanks!

Additionally, I have solved my issue....kind of!

I only swapped some lines of code from


glGenRenderbuffers(1,&fboData.depthBuffer);
glBindRenderbuffer(GL_RENDERBUFFER,fboData.depthBuffer);
glRenderbufferStorage(GL_RENDERBUFFER,GL_DEPTH_COMPONENT,fboData.depthWidth,fboData.depthHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,GL_RENDERBUFFER,fboData.depthBuffer);

glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D,fboData,texID,0);



to


glGenRenderbuffers(1,&fboData.depthBuffer);
glBindRenderbuffer(GL_RENDERBUFFER,fboData.depthBuffer);

glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,GL_RENDERBUFFER,fboData.depthBuffer);
glRenderbufferStorage(GL_RENDERBUFFER,GL_DEPTH_COMPONENT,fboData.depthWidth,fboData.depthHeight);

glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D,fboData.texID,0);


and it kind of works....

Well. What happens is my teapot is now rendered to the screen, but with no movement what so ever. No translation takes place, so no animation is visible! I don't understand it...
Yours3&#33;f
Yours3&#33;f
I don't understand it either smile.png
maybe you don't transform your vertices? (no matrix multiplication in your shaders...)
but in my setup I do it the other way round, renderbufferstorage and then framebufferrenderbuffer.

I took an in-depth look at your code as I had some time for it and I'd do it like this:
void FrameBufferObject(FBO& fboData,GLenum minFilter,GLenum magFilter)
{
glGenFramebuffers(1,&fboData.handle);
glBindFramebuffer(GL_FRAMEBUFFER,fboData.handle);

GLenum drawBufs[] = {GL_COLOR_ATTACHMENT0};
glDrawBuffers(1,drawBufs);


glGenTextures(1,&fboData.textureData.texID);
glBindTexture(GL_TEXTURE_2D,fboData.textureData.texID);
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);

//There is difference between gl_rgba8 and gl_rgba look it up!
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8,fboData.depthWidth,fboData.depthHeight,0,GL_RGBA,GL_UNSIGNED_BYTE,NULL);

glGenRenderbuffers(1,&fboData.depthBuffer);
glBindRenderbuffer(GL_RENDERBUFFER,fboData.depthBuffer);
glRenderbufferStorage(GL_RENDERBUFFER,GL_DEPTH_COMPONENT,fboData.depthWidth,fboData.depthHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,GL_RENDERBUFFER,fboData.depthBuffer);

glFramebufferTexture(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,fboData.textureData.texID,0);

if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
std::cout<<"problem with framebuffer!";
else
std::cout<<"framebuffer ok! smile.png";

glBindFramebuffer(GL_FRAMEBUFFER,0);
}

also don't forget to set the frag data location for
out vec3 color;

in your pixel shaders. This might not be important now, but it may be later.
Lil_Lloyd
Lil_Lloyd

maybe you don't transform your vertices? (no matrix multiplication in your shaders...)


If I comment out the call to render the texture to the screen and comment out the call to BindFrameBuffer in the teapot drawing code the teapot renders to screen rotating fine, so my vertex program for the teapot is ok.

The weirdest part is if I comment out


GLenum drawBufs[] = {GL_COLOR_ATTACHMENT0};
glDrawBuffers(1,drawBufs);


and change

layout(location=0) out vec3 color;

to

out vec3 color;

in the framebuffer setup code it still renders a static teapot as a texture no problem, and checking in GDebugger the texture is rendering ok?!?! There is something very strange here. My Complete code is available here:


#include "..\shared\Includes.h"
#include "..\shared\ShaderUtilities.h"
#include "Texture1.h"
#include "Cube.h"
#include "Teapot.h"
#include "common/shader.hpp"
#include "common/texture.hpp"
#include "common/controls.hpp"
#include "common/objloader.hpp"
#include "common/vboindexer.hpp"
void Render();

GLuint renderProgram,textureProgram,textureUniform;
GLuint MVPMatrixUniform;
Texture testTexture;
GLuint vertexbuffer;
GLuint uvbuffer;
GLuint normalbuffer;
GLuint elementbuffer;

glm::mat4 perspMatrix,MVPMatrix,camMatrix,scaleMatrix,transformMatrix;
VBOTeapot* teapot;
FBO frameBuf;
bool res;
std::vector<unsigned short> indices;
std::vector<glm::vec3> indexed_vertices;
std::vector<glm::vec2> indexed_uvs;
std::vector<glm::vec3> indexed_normals;
// Read our .obj file
std::vector<glm::vec3> vertices;
std::vector<glm::vec2> uvs;
std::vector<glm::vec3> normals;
const std::string strVertexShaderFile1 = "render.vp";
const std::string strFragmentShaderFile1 = "render.fp";
const std::string strVertexShaderFile2 = "texture.vp";
const std::string strFragmentShaderFile2 = "texture.fp";

///////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Function prototypes!
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

void InitVertexBuffer();
GLvoid Reshape(GLsizei width,GLsizei height);
void InitGL();
void DrawGLScene();
void Update();
static const GLfloat g_quad_vertex_buffer_data[] = {
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
-1.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
1.0f, 1.0f, 0.0f,
};
GLuint quad_vertexbuffer;

int main(int argc,char** argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_RGB|GLUT_DOUBLE|GLUT_DEPTH);
glutInitWindowSize(640,480);
glutInitWindowPosition(0,0);
glutCreateWindow("ArcSynth shizznit");
GLenum err = glewInit();
if (GLEW_OK != err)
{
return 1;
}
//int things for this app
InitGL();
//callback funcs
glutDisplayFunc(DrawGLScene);
glutReshapeFunc(Reshape);
glutMainLoop();
glDeleteTextures(1,&frameBuf.texID);
glDeleteBuffers(1,&frameBuf.handle);
delete teapot;
return 0;
}

void InitVertexBuffer()
{
glGenBuffers(1, &quad_vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, quad_vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_quad_vertex_buffer_data), g_quad_vertex_buffer_data, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER,0);
}

GLvoid Reshape(GLsizei width,GLsizei height)
{
if(height == 0)
height = 1;

glViewport(0,0,width,height);
//glMatrixMode(GL_PROJECTION);
//glLoadIdentity();

//glMatrixMode(GL_MODELVIEW);
//glLoadIdentity();
}
void InitProgramSpecificData()
{
MVPMatrixUniform = glGetUniformLocation(renderProgram,"MVPMatrix");
ZeroMemory(&frameBuf,sizeof(frameBuf));
frameBuf.depthWidth = 640;
frameBuf.depthHeight = 480;

FrameBufferObject(frameBuf,GL_NEAREST,GL_NEAREST);
perspMatrix = glm::perspective(45.0f,1.0f,0.2f,600.0f);

teapot = new VBOTeapot(8.0f,glm::translate(0.0f,0.0f,0.0f));
camMatrix = glm::lookAt(glm::vec3(0.0f,2.0f,-7.0f),
glm::vec3(0.0f,2.0f,0.0f),
glm::vec3(0.0f,1.0f,0.0f));
InitVertexBuffer();


}
void InitGL(GLvoid)
{
glShadeModel(GL_SMOOTH);
glClearColor(0.5f,0.0f,0.0f,0.0f);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glEnable(GL_MULTISAMPLE);
InitVertexBuffer();
std::vector<GLchar*> attribs;
attribs.push_back("position");
InitShaderProgram(ReadFile(strVertexShaderFile1),ReadFile(strFragmentShaderFile1),renderProgram,attribs);
InitShaderProgram(ReadFile(strVertexShaderFile2),ReadFile(strFragmentShaderFile2),textureProgram,attribs);
InitProgramSpecificData();

}

void Update()
{
static float angle = 0.0f;
angle += 0.05f;
if(angle > 360.0f)
angle = 0.0f;
glm::mat4 rotateMatrix = glm::rotate(angle,0.0f,1.0f,0.0f);
transformMatrix = rotateMatrix * glm::rotate(-90.0f,1.0f,0.0f,0.0f);
}
void RenderToTexture()
{
glClear(GL_COLOR_BUFFER_BIT |GL_DEPTH_BUFFER_BIT );
glUseProgram(renderProgram);
glUniformMatrix4fv(MVPMatrixUniform,1,GL_FALSE,&MVPMatrix[0][0]);
//set variables for the fbo
glBindFramebuffer(GL_FRAMEBUFFER,frameBuf.handle);
glViewport(0,0,640,480);
glEnableVertexAttribArray(0);
teapot->render();
glUseProgram(0);
glDisableVertexAttribArray(0);
glBindFramebuffer(GL_FRAMEBUFFER,0);
//glBindTexture(GL_TEXTURE_2D,0);
}
void DrawTextureToQuad()
{
glClear(GL_COLOR_BUFFER_BIT |GL_DEPTH_BUFFER_BIT );
glViewport(0,0,640,480);
glUseProgram(textureProgram);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D,frameBuf.texID);
GLuint texID = glGetUniformLocation(textureProgram, "renderedTexture");
glUniform1i(texID,0);
glEnableVertexAttribArray(0);


//Render to the screen
glBindBuffer(GL_ARRAY_BUFFER, quad_vertexbuffer);
glVertexAttribPointer(
0, // attribute 0. No particular reason for 0, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// Draw the triangle !

glDrawArrays(GL_TRIANGLES, 0, 6); // From index 0 to 3 -> 1 triangle
glDisableVertexAttribArray(0);
glUseProgram(0);
}
void DrawGLScene(GLvoid)
{
MVPMatrix = perspMatrix * camMatrix * transformMatrix;
Update();
RenderToTexture();
DrawTextureToQuad();

glutSwapBuffers();
glutPostRedisplay();
}


with framebuffer init code:


void FrameBufferObject(FBO& fboData,GLenum minFilter,GLenum magFilter)
{

glGenFramebuffers(1,&fboData.handle);
glBindFramebuffer(GL_FRAMEBUFFER,fboData.handle);
//GLenum drawBufs[] = {GL_COLOR_ATTACHMENT0};
//glDrawBuffers(1,drawBufs);
glGenTextures(1,&fboData.texID);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D,fboData.texID);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,minFilter);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,magFilter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8,fboData.depthWidth,fboData.depthHeight,0,GL_RGBA,GL_UNSIGNED_BYTE,NULL);
glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D,fboData.texID,0);
glGenRenderbuffers(1,&fboData.depthBuffer);
glBindRenderbuffer(GL_RENDERBUFFER,fboData.depthBuffer);
//glRenderbufferStorage(GL_RENDERBUFFER,GL_DEPTH_COMPONENT,fboData.depthWidth,fboData.depthHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,GL_RENDERBUFFER,fboData.depthBuffer);
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
std::cout<<"problem with framebuffer!";
else
std::cout<<"framebuffer ok! <img src='http://public.gamedev.net//public/style_emoticons/<#EMO_DIR#>/smile.png' class='bbc_emoticon' alt=':)' />";

glBindRenderbuffer(GL_RENDERBUFFER,0);
glBindFramebuffer(GL_FRAMEBUFFER,0);
}

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.