glFramebufferTexture2DEXT

Started by
8 comments, last by eddy_a_j_888 16 years, 1 month ago
The problem: glFramebufferTexture2DEXT seems to be taking an unreasonably long time. I am creating a framebuffer object initialially (once):
Quote: GLuint fbo; glGenFramebuffersEXT(1, &fbo); if(fbo==0) throw("Invalid frame buffer object"); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo); glViewport(0,0,width, height);
then creating a new texture to render to for each frame:
Quote: GLuint texHandle; glGenTextures(1, &texHandle); glEnable(GL_TEXTURE_RECTANGLE_NV); glBindTexture(GL_TEXTURE_RECTANGLE_NV, texHandle); glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, GL_FLOAT_R_NV, width, height, 0, GL_RED, GL_FLOAT, 0); //Where data is a float array of size width * height. glTexSubImage2D(GL_TEXTURE_RECTANGLE_NV, 0, 0, 0, width, height, ret.second, GL_FLOAT, data);
I am then attaching the output texture to the same FBO each time:
Quote: glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_NV, texHandle, 0); if(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) throw("error - frame buffer to texture binding incomplete");
The program is running correctly, but running very slowly. When profiling I found it was the glFramebufferTexture2DEXT function (that which attaches the output texture to the FBO each time) which is taking the time, 0.15 seconds for a 1000x1000 image. Is this what we be expected or am I doing something wrong? [Edited by - eddy_a_j_888 on March 5, 2008 4:38:22 AM]
Advertisement
Quote:Original post by eddy_a_j_888
then creating a new texture to render to for each frame:


There lies your problem.

Y.
what do you mean by this? Each frame uses a different image (i.e. different data is copied into the texture) rather than repeatedly creating a texture for one image, is this what you mean?

Thanks.
He means that you want to be creating the texture _once_ and then using it every frame as your framebuffer.

The "glGenFramebuffersEXT" simply gives you an internal opengl handle (ID) to a fbo.
The "glBindFramebufferEXT" call tells it what you're going to use it for.
The "glFramebufferTexture2DEXT" call actually tells it which texture you're going to be using with the currently active framebuffer and its format etc.

You don't want to be using a different texture for every frame, you just want to bind and setup a single texture for use with a single fbo that you then use every frame. Creating that texture and fbo and re-binding it every frame are complex processes that change a lot of state within opengl and the gfx card.

Andy

"Ars longa, vita brevis, occasio praeceps, experimentum periculosum, iudicium difficile"

"Life is short, [the] craft long, opportunity fleeting, experiment treacherous, judgement difficult."

Quote:Original post by eddy_a_j_888
what do you mean by this? Each frame uses a different image (i.e. different data is copied into the texture) rather than repeatedly creating a texture for one image, is this what you mean?

Thanks.


This use of terminology is confusing. Each frame creates the "image" that is rendered into the texture that you specified. It simply has to overwrite each previous frame within that same texture.

// terrible pseudo-code example
///////////////////////////////
gen texture handle
bind texture handle
attach texture data to active texture //glTexSubImage2D

gen fbo handle
bind fbo handle
attach fbo texture to active fbo //glFramebufferTexture2DEXT
while not finished
{
     render into fbo
     display fbo
}

Hope that makes some sense. If not maybe Ysaneya can help dig you out but there is also an FBO Example tutorial on gamedev.

Andy

"Ars longa, vita brevis, occasio praeceps, experimentum periculosum, iudicium difficile"

"Life is short, [the] craft long, opportunity fleeting, experiment treacherous, judgement difficult."

Quote:Original post by eddy_a_j_888
...
//Where data is a float array of size width * height.
glTexSubImage2D(GL_TEXTURE_RECTANGLE_NV, 0, 0, 0, width, height, ret.second, GL_FLOAT, data);
...
Also, since you're just rendering into the this texture every frame, there's no reason to set the texel data every frame. Even if you kept creating a new texture every frame (this is a very bad idea, as has been said) that is just more wasted time; calling glTexImage2D with a null pointer for data will allocate enough memory to accommodate a width x height texture, the image data will just be undefined. Since you're presumably rendering to the texture before you use it, it doesn't matter that the image data is undefined before this.
Sorry for the confusion.

I am using the code to do off-screen calculations. In this case I am adding two different images together each time. However, I want to do the next addition while still having access to the previous sum (texture). Therefore I need to create another texture and attach it to the FBO (dettaching the previous one but keeping the handle to it) so that the next addition can be run. The computation is run straight after the glFramebufferTexture2DEXT call.

Also, I realise I made an error in saying I called:
Quote:
glTexSubImage2D(GL_TEXTURE_RECTANGLE_NV, 0, 0, 0, width, height, ret.second, GL_FLOAT, data);


As this texture I have just created is the result of the calculation, it does not require any data as its data is about to be calculated.

I hope I've cleaned things up, if I'm still being stupid do tell!

Thanks all.
In which case you only need two textures, created once at start up. You then swap which is the source and which is the destination each frame.

Frame one; src = 0, dest = 1
Frame two; src = 1, dest = 0

And so on.

It is possible to infact have both attached to the FBO at once and just swap the destination attachment.

Some really cool guy on these forums wrote not just one, but two articles on using FBOs, including handling attachments like this.

Quote:Original post by eddy_a_j_888
...
However, I want to do the next addition while still having access to the previous sum (texture).
...
In this case you only need two textures. Create them both up front, initialize one with whatever default data will be used for the first run of the calculations, bind that (texture A) as the input texture, bind the other texture (texture B) as the render target and perform your rendering/calculations. Then for the next frame you just swap the textures; texture B becomes the next frame's input texture and texture A becomes the render target.

EDIT: Doh, too slow.
I think you're right! Thanks for the help - i'm on it!

Out of interest, does anyone have a link to the glFramebufferTexture2DEXT function spec, i've found it mentioned in the framebuffer object spec but not actually explained. what does this function do? It seems it takes a long time the first time this function is run with a new texture (thus having two textures would solve the problem), but out of interest why is this so? Is it formatting?

This topic is closed to new replies.

Advertisement