Sign in to follow this  
Yours3!f

OpenGL fbo not working

Recommended Posts

Hi,

I tried to render to a texture and render it later as a full-screen quad. However the screen remains black. I checked the fbo, no errors it is complete, I checked the shaders, they're working, I checked the render texture on another object, and it contains the scene data, and I could display it. I checked the full-screen quad that I draw the texture onto, and I can draw it too, but to be sure I disabled backface culling while drawing the fs quad. I get no opengl error, I can pass all the stuff to the shaders, I get no error while loading them too. I tried immediate mode drawing too, but it didn't help. The scene is drawn properly when not using RTTs.

Here's the loading code:
[code]
//load in the shaders
objs::get()->shader_loader.load_shader_control_file ( "../shaders/deferred/fs_quad.sc", &the_render.fs_quad );
//load in the full-screen quad from an obj file
objs::get()->obj.load_obj_file ( "../resources/fs_quad.obj", &the_render.quad, &the_render.fs_quad );

//create the texture to render to
the_render.fbo_tex.create();
the_render.fbo_tex.bind();
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_RGBA16F, objs::get()->conf.SCREEN_WIDTH, objs::get()->conf.SCREEN_HEIGHT, 0, GL_RGBA, GL_FLOAT, 0 );
the_render.fbo_tex.set_dimensions ( objs::get()->conf.SCREEN_WIDTH, objs::get()->conf.SCREEN_HEIGHT );

//create the render buffer that contains the depth data
the_render.rbuf_depth.create();
the_render.rbuf_depth.bind();
the_render.rbuf_depth.set_storage_format ( GL_DEPTH_COMPONENT32, objs::get()->conf.SCREEN_WIDTH, objs::get()->conf.SCREEN_HEIGHT );

//create fbo that will contain the color data
the_render.fbo.create();
the_render.fbo.bind();
the_render.fbo.set_as_draw_buffer ( GL_COLOR_ATTACHMENT0 );

//attach render buffer to the frame buffer
the_render.rbuf_depth.attach_to_frame_buffer ( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, &the_render.fbo );
//attach the texture to the frame buffer
the_render.fbo_tex.attach_to_frame_buffer ( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &the_render.fbo );

//unbind the fbo
the_render.fbo.unbind();
[/code]

here's the render code:
[code]
//set up camera...

//bind fbo
fbo.bind();
clear_screen();
//draw stuff....
fbo.unbind();

//set orhographic mode, disable depth testing, bind the fs quad shader
event::get()->get_resize()->set_orthographic ( objs::get()->conf.SCREEN_WIDTH, objs::get()->conf.SCREEN_HEIGHT, -1.0f, 1.0f );
glDisable ( GL_DEPTH_TEST );
fs_quad.bind();

//pass the matrices
fs_quad.pass_m4x4 ( objs::get()->ppl.get_projection_matrix(), "m4_p" );
fs_quad.pass_m4x4 ( objs::get()->ppl.get_model_view_matrix(), "m4_mv" );

//bind the texture and set up texture parameters
fbo_tex.bind();
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri ( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri ( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
//pass the texture to the shader
fs_quad.pass_int ( 0, "texture0" );

//draw full-screen quad
quad.render();

//unbind shader, enable depth test, set perspective mode again
fs_quad.unbind();
glEnable ( GL_DEPTH_TEST );
event::get()->get_resize()->set_perspective ();

objs::get()->check_for_opengl_error();
swap_buffer();
[/code]

vertex shader:
[code]
#version 410

//projection, modelview matrices
uniform mat4 m4_p, m4_mv;

//the vertex position
in vec4 v4_vertex;
//the texture coordinates
in vec2 v2_texture;

smooth out vec2 v2_texture_coords;

void main()
{
v2_texture_coords = v2_texture;
mat4 m4_mvp = m4_p * m4_mv;
gl_Position = m4_mvp * v4_vertex;
}
[/code]

pixel shader code:
[code]
#version 410

uniform sampler2D texture0;

smooth in vec2 v2_texture_coords;

out vec4 v4_frag_color;

void main()
{
v4_frag_color = texture(texture0, v2_texture_coords.st);
}
[/code]

and the obj file:
[code]
v 1.000000 -1.000000 0.000000
v 1.000000 1.000000 0.000000
v -1.000000 1.000000 0.000000
v -1.000000 -1.000000 0.000000
vt 0.000000 0.000000
vt 1.000000 0.000000
vt 1.000000 1.000000
vt 0.000000 1.000000
f 3/3/ 4/2/ 1/1/
f 2/4/ 3/3/ 1/1/
[/code]

What am I missing?

Best regards,
Yours3!f

Share this post


Link to post
Share on other sites
[quote name='Yours3!f' timestamp='1313066471' post='4847647']
[code]
//pass the texture to the shader
fs_quad.pass_int ( 0, "texture0" );
[/code]
[/quote]

Any reason why this is 0?

Share this post


Link to post
Share on other sites
[quote name='capricorn' timestamp='1313068285' post='4847658']
[quote name='Yours3!f' timestamp='1313066471' post='4847647']
[code]
//pass the texture to the shader
fs_quad.pass_int ( 0, "texture0" );
[/code]
[/quote]

Any reason why this is 0?
[/quote]

as far as I know if you bind a texture, then there is no need to pass anything but a zero as the variable to the shader (to the sampler2D).

Share this post


Link to post
Share on other sites
Hidden
[quote name='Yours3!f' timestamp='1313066471' post='4847647']
Hi,

I tried to render to a texture and render it later as a full-screen quad. However the screen remains black. I checked the fbo, no errors it is complete, I checked the shaders, they're working, I checked the render texture on another object, and it contains the scene data, and I could display it. I checked the full-screen quad that I draw the texture onto, and I can draw it too, but to be sure I disabled backface culling while drawing the fs quad. I get no opengl error, I can pass all the stuff to the shaders, I get no error while loading them too. I tried immediate mode drawing too, but it didn't help. The scene is drawn properly when not using RTTs.

Here's the loading code:
[code]
//load in the shaders
objs::get()->shader_loader.load_shader_control_file ( "../shaders/deferred/fs_quad.sc", &the_render.fs_quad );
//load in the full-screen quad from an obj file
objs::get()->obj.load_obj_file ( "../resources/fs_quad.obj", &the_render.quad, &the_render.fs_quad );

//create the texture to render to
the_render.fbo_tex.create();
the_render.fbo_tex.bind();
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_RGBA16F, objs::get()->conf.SCREEN_WIDTH, objs::get()->conf.SCREEN_HEIGHT, 0, GL_RGBA, GL_FLOAT, 0 );
the_render.fbo_tex.set_dimensions ( objs::get()->conf.SCREEN_WIDTH, objs::get()->conf.SCREEN_HEIGHT );

//create the render buffer that contains the depth data
the_render.rbuf_depth.create();
the_render.rbuf_depth.bind();
the_render.rbuf_depth.set_storage_format ( GL_DEPTH_COMPONENT32, objs::get()->conf.SCREEN_WIDTH, objs::get()->conf.SCREEN_HEIGHT );

//create fbo that will contain the color data
the_render.fbo.create();
the_render.fbo.bind();
the_render.fbo.set_as_draw_buffer ( GL_COLOR_ATTACHMENT0 );

//attach render buffer to the frame buffer
the_render.rbuf_depth.attach_to_frame_buffer ( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, &the_render.fbo );
//attach the texture to the frame buffer
the_render.fbo_tex.attach_to_frame_buffer ( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, &the_render.fbo );

//unbind the fbo
the_render.fbo.unbind();
[/code]

here's the render code:
[code]
//set up camera...

//bind fbo
fbo.bind();
//clear screen...
//draw stuff....
fbo.unbind();

//set orhographic mode, disable depth testing, bind the fs quad shader
event::get()->get_resize()->set_orthographic ( objs::get()->conf.SCREEN_WIDTH, objs::get()->conf.SCREEN_HEIGHT, -1.0f, 1.0f );
glDisable ( GL_DEPTH_TEST );
fs_quad.bind();

//pass the matrices
fs_quad.pass_m4x4 ( objs::get()->ppl.get_projection_matrix(), "m4_p" );
fs_quad.pass_m4x4 ( objs::get()->ppl.get_model_view_matrix(), "m4_mv" );

//bind the texture and set up texture parameters
fbo_tex.bind();
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri ( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri ( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
//pass the texture to the shader
fs_quad.pass_int ( 0, "texture0" );

//draw full-screen quad
quad.render();

//unbind shader, enable depth test, set perspective mode again
fs_quad.unbind();
glEnable ( GL_DEPTH_TEST );
event::get()->get_resize()->set_perspective ();

objs::get()->check_for_opengl_error();
swap_buffer();
[/code]

vertex shader:
[code]
#version 330

//projection, modelview matrices
uniform mat4 m4_p, m4_mv;

//the vertex position
in vec4 v4_vertex;
//the texture coordinates
in vec2 v2_texture;

smooth out vec2 v2_texture_coords;

void main()
{
v2_texture_coords = v2_texture;
mat4 m4_mvp = m4_p * m4_mv;
gl_Position = m4_mvp * v4_vertex;
}
[/code]

pixel shader code:
[code]
#version 330

uniform sampler2D texture0;

smooth in vec2 v2_texture_coords;

out vec4 v4_frag_color;

void main()
{
v4_frag_color = texture(texture0, v2_texture_coords.st);
}
[/code]

and the obj file:
[code]
v 1.000000 -1.000000 0.000000
v 1.000000 1.000000 0.000000
v -1.000000 1.000000 0.000000
v -1.000000 -1.000000 0.000000
vt 0.000000 0.000000
vt 1.000000 0.000000
vt 1.000000 1.000000
vt 0.000000 1.000000
f 3/3/ 4/2/ 1/1/
f 2/4/ 3/3/ 1/1/
[/code]

What am I missing?

Best regards,
Yours3!f
[/quote]

Share this post


Link to post
[quote name='Yours3!f' timestamp='1313068976' post='4847666']
as far as I know if you bind a texture, then there is no need to pass anything but a zero as the variable to the shader (to the sampler2D).
[/quote]

Nope. Binding a texture is only required for those stages of fixed pipeline that operate on it (setting image, filters, etc.). sampler2D should contain actual texture ID. You pass a 'default' textureID (0) to shader, that's why all you see is a black quad :)

Share this post


Link to post
Share on other sites
[quote name='capricorn' timestamp='1313069182' post='4847668']
[quote name='Yours3!f' timestamp='1313068976' post='4847666']
as far as I know if you bind a texture, then there is no need to pass anything but a zero as the variable to the shader (to the sampler2D).
[/quote]

Nope. Binding a texture is only required for those stages of fixed pipeline that operate on it (setting image, filters, etc.). sampler2D should contain actual texture ID. You pass a 'default' textureID (0) to shader, that's why all you see is a black quad :)
[/quote]

but I do it everywhere else, and it works... anyways I tried it:
[code]
fs_quad.pass_int ( *fbo_tex.get_id(), "texture0" ); //the returned id is the GLuint of the texture

//draw full-screen quad
quad.render();
[/code]

but at the quad.render() function it crashes. this is the last call from my application, and there are some from the gpu driver :) (fglrx_dri.so)

Share this post


Link to post
Share on other sites
[quote name='capricorn' timestamp='1313069182' post='4847668']
[quote name='Yours3!f' timestamp='1313068976' post='4847666']
as far as I know if you bind a texture, then there is no need to pass anything but a zero as the variable to the shader (to the sampler2D).
[/quote]

Nope. Binding a texture is only required for those stages of fixed pipeline that operate on it (setting image, filters, etc.). sampler2D should contain actual texture ID. You pass a 'default' textureID (0) to shader, that's why all you see is a black quad :)
[/quote]

Nope, sampler2D should contain the texture unit unit number. It starts from 0 and goes to GL_MAX_whatever (GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS or GL_MAX_TEXTURE_IMAGE_UNITS)
http://www.opengl.org/wiki/GLSL_:_common_mistakes#Binding_A_Texture

Share this post


Link to post
Share on other sites
[quote name='V-man' timestamp='1313070921' post='4847678']
[quote name='capricorn' timestamp='1313069182' post='4847668']
[quote name='Yours3!f' timestamp='1313068976' post='4847666']
as far as I know if you bind a texture, then there is no need to pass anything but a zero as the variable to the shader (to the sampler2D).
[/quote]

Nope. Binding a texture is only required for those stages of fixed pipeline that operate on it (setting image, filters, etc.). sampler2D should contain actual texture ID. You pass a 'default' textureID (0) to shader, that's why all you see is a black quad :)
[/quote]

Nope, sampler2D should contain the texture unit unit number. It starts from 0 and goes to GL_MAX_whatever (GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS or GL_MAX_TEXTURE_IMAGE_UNITS)
[url="http://www.opengl.org/wiki/GLSL_:_common_mistakes#Binding_A_Texture"]http://www.opengl.or...nding_A_Texture[/url]
[/quote]

ok but that is for multi-texturing right? and since there is only one texture and I don't use multi-texturing anywhere else it should work, shouldn't it?

anyways the driver should've given me an opengl error, not crashing :blink:

Share this post


Link to post
Share on other sites
[quote name='V-man' timestamp='1313070921' post='4847678']
Nope, sampler2D should contain the texture unit unit number.
[/quote]

Ugh, what I was smoking? [img]http://public.gamedev.net/public/style_emoticons/default/blink.gif[/img] Should go slap myself in the head a couple times. Apologies, Yours3!f.

Share this post


Link to post
Share on other sites
[quote name='capricorn' timestamp='1313072198' post='4847689']
[quote name='V-man' timestamp='1313070921' post='4847678']
Nope, sampler2D should contain the texture unit unit number.
[/quote]

Ugh, what I was smoking? [img]http://public.gamedev.net/public/style_emoticons/default/blink.gif[/img] Should go slap myself in the head a couple times. Apologies, Yours3!f.
[/quote]

no problem :) you've just discovered a bug in the linux ATI drivers as it's not giving an error when using a GLint > max
actually the texture id was 707, so I tried to use my video card excessively lol

Share this post


Link to post
Share on other sites
Ok, I think I started getting it... I replace the rendering code (quad.render()) with this immediate mode code:
[code]
float w = objs::get()->conf.SCREEN_WIDTH;
float h = objs::get()->conf.SCREEN_HEIGHT;
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 1.0f);
glVertex2f(-w, h);
glTexCoord2f(1.0f, 1.0f);
glVertex2f(w, h);
glTexCoord2f(1.0f, 0.0f);
glVertex2f(w, -h);
glTexCoord2f(0.0f, 0.0f);
glVertex2f(-w, -h);
glEnd();
[/code]

now my screen gone from black to grey... but I still don't get my scene.... but why is that this immediate code doesn't work?
[code]
float w = 1
float h = 1
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 1.0f);
glVertex2f(-w, h);
glTexCoord2f(1.0f, 1.0f);
glVertex2f(w, h);
glTexCoord2f(1.0f, 0.0f);
glVertex2f(w, -h);
glTexCoord2f(0.0f, 0.0f);
glVertex2f(-w, -h);
glEnd();
[/code]

EDIT: I thought my I set up my fbo wrong that's why my fbo is grey, so I tried setting it up with these settings:
[code]
glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGBA8, objs::get()->conf.SCREEN_WIDTH, objs::get()->conf.SCREEN_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0 );
the_render.rbuf_depth.set_storage_format ( GL_DEPTH_COMPONENT, objs::get()->conf.SCREEN_WIDTH, objs::get()->conf.SCREEN_HEIGHT );
[/code]

but it remained the same...

Share this post


Link to post
Share on other sites
Ok I finally solved it. The problem was with the orthographic matrix. I needed to use 1 as with and 1 as height -1 as near and 1 as far.
To add the obj file's vertices were in the wrong order and the texture coordinates were upside down. So changing that solved the problem.

Here's the final rendering code:
[code]
clear_screen(); //clearing the screen so that non-fbo stuff such as text can be drawn
fbo.bind();
clear_screen(); //now clearing the fbo

//set up camera and draw stuff

fbo.unbind();

//draw fbo
event::get()->get_resize()->set_orthographic ( 1.0f, 1.0f, -1.0f, 1.0f );
fs_quad.bind();

fs_quad.pass_m4x4 ( objs::get()->ppl.get_projection_matrix(), "m4_p" );
fs_quad.pass_m4x4 ( objs::get()->ppl.get_model_view_matrix(), "m4_mv" );

fbo_tex.bind();
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri ( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri ( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
fs_quad.pass_int ( 0, "texture0" );

//draw full-screen quad
quad.render();

fs_quad.unbind();
event::get()->get_resize()->set_perspective ();

//draw text, non-fbo stuff

swap_buffer();
[/code]

and the final obj file:
[code]
# Blender v2.58 (sub 1) OBJ File: ''
# www.blender.org
v 1.000000 0.000000 0.000000
v 1.000000 1.000000 0.000000
v 0.000000 1.000000 0.000000
v 0.000000 0.000000 0.000000
vt 0.000000 0.000000
vt 1.000000 0.000000
vt 1.000000 1.000000
vt 0.000000 1.000000
f 3/1/ 2/2/ 1/3/
f 1/3/ 4/4/ 3/1/
[/code]

The vertices in the obj file are in ccw order. To draw the full-screen quad I didn't even need to disable depth test and face culling. The fbo texture with the original setup (rgba16f and rgba and float) works, and the depth component remained depth_component32

Thanks for the help guys!

Share this post


Link to post
Share on other sites
isn't this wrong?

glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri ( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri ( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this