Framebuffer trouble (now texture trouble all around)

Started by
5 comments, last by V-man 12 years, 3 months ago
I need to use a Framebuffer object in my current project and I have never worked with them before. I read several tutorials, and the help provided here: http://www.opengl.org/wiki/Framebuffer_Object

But my own system is not working. I have debugged, and what I found was that after I generate the texture id and bind it to GL_FRAMEBUFFER and then attach a texture to the first color buffer the function glIsFramebuffer returns false, as does glIsBuffer. (I wasn't sure if there was a difference there.)

Here is my code for creating the FBO. If you need to see anything else ask, but I am not sure that it would be relevant unless this problem gets solved.


// texture
GLuint tex;
glGenTextures(1,&tex);
glBindTexture(GL_TEXTURE_RECTANGLE_NV,tex);
glTexImage2D(GL_TEXTURE_RECTANGLE_NV,0,GL_RGBA8,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,0); // should generate blank pixel data

glTexParameteri(GL_TEXTURE_RECTANGLE_NV,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_RECTANGLE_NV,GL_TEXTURE_MAG_FILTER,GL_LINEAR);



bool is = glIsTexture(tex);
if (!is)
throw "texture not real";

GLuint fbo, ren;
// render buffer - not sure if this is required
glGenRenderbuffers(1, &ren);
glBindRenderbuffer(GL_RENDERBUFFER,ren);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, w, h);

// framebuffer
glGenBuffers(1,&fbo);
glBindBuffer(GL_FRAMEBUFFER,fbo);

// attachments
glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_RECTANGLE_NV,tex,0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, ren);

is = glIsBuffer(fbo);
if (!is)
throw "framebuffer not real";

auto er = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (er != GL_FRAMEBUFFER_COMPLETE){
throw "framebuffer failed to complete";
}

ptr->fboid = fbo;
ptr->tid = tex;
glClearColor(1,1,1,1);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glBindFramebuffer(GL_FRAMEBUFFER,0);


Thanks for the help.

EDIT: Ok this is embarrassing but I figured out the above problem, the fbo now works... kinda... I have a different problem though.
(Above the problem was I used glGenBuffers which, it turns out is different than glGenFramebuffers)

So now I have a new problem, when I try to draw the texture onto the screen it does not show up. I know that I am binding the framebuffer correctly because if I leave it (don't bind back to the screen) it flashes black and white (which is it flipping the buffers on the screen with nothing on them due to all the rendering going to my own framebuffer). I know that its not any of my rendering settings because when I don't leave it bound my normal sprites work correctly, moving as they should. I have tried setting the matrices up for the surface when I try to render to it. (I am not sure if I need to do that). I have tried using the matrices with the screen settings, with settings to match the texture size, and with settings of glOrtho(0,1,1,0,-1,1). (If I didn't mention this is 2D not 3D). Even if the sprites are not rendering correctly I tried clearing the texture with black and it is not showing up even now.

Here is my rendering to the fbo code

ore::Surface surface;
ore::SurfaceF::New(&surface,100,100);
ore::Screen::Set(&surface);

/*
glMatrixMode(GL_PROJECTION); // projection
glPushMatrix();
glLoadIdentity();
glOrtho(0, 100, 100, 0, -50, 50);
glMatrixMode(GL_MODELVIEW); // modelview
glPushMatrix();
glLoadIdentity();
*/

ore::SpriteF::Render(&spinner,25,50);
ore::SpriteF::Render(&spinner,75,50);

ore::Screen::Reset();
/*
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
*/


And here is my function for rendering the surface

int w = ptr->w,
h = ptr->h;
glBindTexture(GL_TEXTURE_RECTANGLE_NV,ptr->tid);
glBegin(GL_QUADS);
{
glTexCoord2i(0, 0); glVertex2i(x, y);
glTexCoord2i(w, 0); glVertex2i(x+w, y);
glTexCoord2i(w, h); glVertex2i(x+w, y+h);
glTexCoord2i(0, h); glVertex2i(x, y+h);
}
glEnd();
Advertisement
The problem is probably either a texture format not supported by the FBO or the FBO views the texture as incomplete.

First, I would try setting the GL_TEXTURE_WRAP_S and GL_TEXTURE_WRAP_T parameters and see if that works. If that doesn't work, another culprit is that the GL_TEXTURE_RECTANGLE_NV target may be causing issues. I would try using GL_TEXTURE_2D as well.
It helped, the FBO is now at least rendering something onto the screen, but its not correct. I did some investigating here's what I've got. If I do load in the texture for my sprite before I create the buffer, it for some reason just has the texture in the top left corner and some black artifacts here and there. If I do nothing it is solid white, (I set the color to 0,0,0,0 hoping it would be transparent, do I need to disable the blending mode for it to work?), if I attempt to render to it using just a rectangle function it becomes black.

Also, I didn't notice a difference but since it's GL_TEXTURE_2D will I need to use powers of 2 for my width and height?
Did you try setting the texture parameters before calling glTexImage2D?


do I need to disable the blending mode for it to work?


On the contrary, you should enable blending. Also, make sure the glBlendFunc is set correctly.


will I need to use powers of 2 for my width and height?


Power of 2 textures are required for mip mapping and older drivers don't support non power of 2 textures. They're strongly recommended.
So I have switched all of the textures to TEXTURE_2D, and then debugged to find that a number of errors were occurring. Before I fixed them both the sprite and the FBO were simply rendering colored boxes, so I started by checking if the texture was real before rendering it (glIsTexture) and it turned out they were not, so I tracked down several errors:

(I should mention, I've never gotten TEXTURE_2D to work, which is why we agreed on using rectangle, but now we need the off screen rendering so I am going to ask for help on the TEXTURE_2D.)

First, I was using glGenBuffers instead of glGenFramebuffers. This fixed the framebuffer. (By fixed I don't mean its working now just no errors).

Secondly, I discovered that the way I was creating surfaces in SDL was causing an error because I had the bitperpixel set to 0 (not sure why) so the format tag for the glTexImage2D function was invalid.

Finally, I got an invalid value error. I investigated and found that the format was GL_BGRA which I thought was odd, because it had been GL_RGBA before I switched texture types, so I manually put in GL_RGBA and it actually removed the error.

But now that the texture for both the sprite, and the surface exist, they are blank. I will provide the code I use to create both.

Loading the image, and using SDL to blit it onto a POT surface:



SDL_Surface *img = IMG_Load(file);
if (w == -1){
w = img->w;
h = img->h;
}

SDL_Surface *scrn = Screen::GetReal();
SDL_Surface *surf = ::SDL_CreateRGBSurface(scrn->flags, UpgradePow2(w), UpgradePow2(h), 32,
scrn->format->Rmask, scrn->format->Gmask, scrn->format->Bmask, scrn->format->Amask);
if (img){
SDL_Rect clip, sprite;
clip.x = x;
clip.y = y;
clip.w = w;
clip.h = h;
sprite.x = sprite.y = 0;
SDL_BlitSurface(img,&clip,surf,&sprite);
if (surf){
SDL_FreeSurface(img);
ptr->ox = 0;
ptr->oy = 0;
ptr->w = w;
ptr->h = h;
_ToGl(ptr,surf);
}else{
SDL_FreeSurface(img);
throw std::exception("failed to clip image correctly");
}
}else{
throw std::exception("failed to load image correctly");
}


The _ToGl function which takes the SDL_Surface (which is POT) and creates a texture:



glGenTextures(1,&spr->tid);
glBindTexture(GL_TEXTURE_2D, spr->tid);

SDL_PixelFormat *format = surf->format; // going to be accessing format a few times
if (format->BytesPerPixel == 4){ // has alpha
if (format->Rmask == 0x000000ff)
spr->glformat = GL_RGBA;
else spr->glformat = GL_BGRA;
}else if (format->BytesPerPixel == 3){// no alpha
if (format->Rmask == 0x000000ff)
spr->glformat = GL_RGB;
else spr->glformat = GL_BGR;
}
// ignore the format and override with RGBA for now
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, surf->w, surf->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surf->pixels);

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
SDL_FreeSurface(surf);




That is all for the sprites, then creating the surface (FBO) is pretty similar to the code in the first post, except for the changes I have mentioned.
I can't speak to the SDL code, but the one thing I see wrong with the GL code is the calls to glTexParameteri are occuring after glTexImage2D. Those calls should go before. Can you confirm that surf->pixels is correct? Are you sure you have texture mapping enabled when it's time to render the texture?

I can't speak to the SDL code, but the one thing I see wrong with the GL code is the calls to glTexParameteri are occuring after glTexImage2D. Those calls should go before. Can you confirm that surf->pixels is correct? Are you sure you have texture mapping enabled when it's time to render the texture?


No, you can call when you want to call it.
Sig: http://glhlib.sourceforge.net
an open source GLU replacement library. Much more modern than GLU.
float matrix[16], inverse_matrix[16];
glhLoadIdentityf2(matrix);
glhTranslatef2(matrix, 0.0, 0.0, 5.0);
glhRotateAboutXf2(matrix, angleInRadians);
glhScalef2(matrix, 1.0, 1.0, -1.0);
glhQuickInvertMatrixf2(matrix, inverse_matrix);
glUniformMatrix4fv(uniformLocation1, 1, FALSE, matrix);
glUniformMatrix4fv(uniformLocation2, 1, FALSE, inverse_matrix);
Ok, I am pretty sure my problem is in fact the sdl code at this point, I tried saving a file of the sdl surface and it only contains the image when I load it in, not after I try to blit it to the resized surface. As far as texture mapping, I am not entirely sure if I have it enabled. If I understand it correctly all I need is glEnable(GL_TEXTURE_2D) is there anything else I need to enable? (For texture mapping that is, I have the other enables locked down.)

EDIT:
I have fixed the sdl code now, so the surface actually has the image it is suppose to but it is still not on the screen correctly. Its hard to describe what's happening. Its the current draw color, but its not a solid rectangle as if I were just drawing a quad with no texture. Instead it looks like a grid. When I tried rotating it the boxes in the grid changed size. Not sure how to describe it, or if it even helps. But it seems to be pretty close now. (Note when I tried to load in pots images before without any sdl bliting for resizing, it gave me the same thing, so I suspect I am doing something wrong with the texture mapping.)

If I understand it correctly all I need is glEnable(GL_TEXTURE_2D) is there anything else I need to enable?


glEnable(GL_TEXTURE_2D) is all you need.



glBegin(GL_QUADS);
{
glTexCoord2i(0, 0); glVertex2i(x, y);
glTexCoord2i(w, 0); glVertex2i(x+w, y);
glTexCoord2i(w, h); glVertex2i(x+w, y+h);
glTexCoord2i(0, h); glVertex2i(x, y+h);
}



With the texture coordinates here, try this instead:


glTexCoord2f(0.0f, 0.0f); ...
glTexCoord2f(1.0f, 0.0f); ...
glTexCoord2f(1.0f, 1.0f); ...
glTexCoord2f(0.0f, 1.0f); ...


That's assuming your code hasn't changed there.

If you want your texture to show up with its true colors, then you should ensure that the draw color is white when you render the texture.
I would try what you said, but matters have somehow gotten even worse. Whenever I create a sprite, all rendering stops. I have generic functions for boxes and lines that stop working after I load a sprite. The only thing that remains is the background color. I looked into it, and its the call:

glTexImage2D(GL_TEXTURE_2D, 0, spr->glformat, surf->w, surf->h, 0, spr->glformat, GL_UNSIGNED_BYTE, surf->pixels);

spr->glformat is GL_RGBA
surf->w is 64
surf->h is 128

that causes the problem, I can't explain whats going on anymore. Sorry if I seem like I have no idea what I'm doing, I have never tried to make texture_2d work before because it never works for me. I am not sure if there is other code you need to see specify and I will provide.

EDIT:
Figured it out... apparently I will need to unbind my textures in order to draw generics, kinda makes sense I suppose. Now my textures is appearing as a white box... as if it doesn't exist again. sigh.

EDIT2:
Finally, it was the
glTexCoord2f(0.0f, 0.0f);
as you suggested that made the 2d textures work. I had to adjust it since I didn't want the full image but it all works out very nicely now... back to the framebuffer hopefully it will be working now.

This topic is closed to new replies.

Advertisement