Jump to content
  • Advertisement
Sign in to follow this  
4th_dimention

OpenGL Framebuffer trouble (now texture trouble all around)

This topic is 2541 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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();
Edited by 4th_dimention

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites
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.)

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!