views:

3232

answers:

1

I'm trying to render to a texture, then draw that texture to the screen using OpenGL ES on the iPhone. I'm using this question as a starting point, and doing the drawing in a subclass of Apple's demo EAGLView.

Instance variables:

GLuint textureFrameBuffer;
Texture2D * texture;

To initialize the frame buffer and texture, I'm doing this:

GLint oldFBO;
glGetIntegerv(GL_FRAMEBUFFER_BINDING_OES, &oldFBO);

// initWithData results in a white image on the device (works fine in the simulator)
texture = [[Texture2D alloc] initWithImage:[UIImage imageNamed:@"blank320.png"]];

// create framebuffer
glGenFramebuffersOES(1, &textureFrameBuffer);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, textureFrameBuffer);

// attach renderbuffer
glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, texture.name, 0);

if(glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES)
    NSLog(@"incomplete");

glBindFramebufferOES(GL_FRAMEBUFFER_OES, oldFBO);

Now, if I simply draw my scene to the screen as usual, it works fine:

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// draw some triangles, complete with vertex normals
[contentDelegate draw];
[self swapBuffers];

But, if I render to 'textureFrameBuffer', then draw 'texture' to the screen, the resulting image is upside down and "inside out". That is, it looks as though the normals of the 3d objects are pointing inward rather than outward -- the frontmost face of each object is transparent, and I can see the inside of the back face. Here's the code:

GLint oldFBO;
glGetIntegerv(GL_FRAMEBUFFER_BINDING_OES, &oldFBO);

glBindFramebufferOES(GL_FRAMEBUFFER_OES, textureFrameBuffer);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// draw some polygons
[contentDelegate draw];

glBindFramebufferOES(GL_FRAMEBUFFER_OES, oldFBO);

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnable(GL_TEXTURE_2D);
glColor4f(1, 1, 1, 1);
[texture drawInRect:CGRectMake(0, 0, 320, 480)];    
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_2D);

[self swapBuffers];

I can flip the image rightside-up easily enough by reordering the (glTexCoordPointer) coordinates accordingly (in Texture2D's drawInRect method), but that doesn't solve the "inside-out" issue.

I tried replacing the Texture2D texture with a manually created OpenGL texture, and the result was the same. Drawing a Texture2D loaded from a PNG image works fine.

As for drawing the objects, each vertex has a unit normal specified, and GL_NORMALIZE is enabled.

glVertexPointer(3, GL_FLOAT, 0, myVerts);
glNormalPointer(GL_FLOAT, 0, myNormals);
glDrawArrays(GL_TRIANGLES, 0, numVerts);

Everything draws fine when it's rendered to the screen; GL_DEPTH_TEST is enabled and is working great.

Any suggestions as to how to fix this? Thanks!

A: 

The interesting part of this is that you're seeing a different result when drawing directly to the backbuffer. Since you're on the iPhone platform, you're always drawing to an FBO, even when you're drawing to the backbuffer.

Make sure that you have a depth buffer attached to your offscreen FBO. In your initialization code, you might want to add the following snippet right after the glBindFramebufferOES(...).

// attach depth buffer
GLuint depthRenderbuffer;
glGenRenderbuffersOES(1, &depthRenderbuffer);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, width, height);
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
prideout
You may be on to something, but it's not working just yet... After doing that and attaching the texture (as before), glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) returns GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_OES. Does the frameBuffer need a color renderbuffer attached to it as well? (Tried that quickly, no luck yet, but I'll keep at it.) Thanks for your help by the way, I really appreciate it.
sb
Oh, I meant to add that rendering to the backbuffer, then copying into my image using glCopyTexSubImage2D then displaying the image works (everything draws the way it should), it's just painfully slow. Back to figuring out what's wrong with my buffer...
sb
Interesting. Yes, you do need to attach a color renderbuffer as well.By the way, this isn't related, but you might want to ensure that your texture object has a power-of-two size so that it works with older iPhones.Good luck!
prideout
Well, I've since moved on from the project, and didn't get around to setting up all the proper buffers. I'm marking this as correct, because it _probably_ is. If I ever come back to it, I'll post my working code here.
sb