PDA

View Full Version : Trouble Rendering Texture to FBO



DoubleJ
01-12-2010, 03:17 PM
Note: I'm doing iPhone programming using OpenGL ES 1.1, so there are lots of features not available to me. (such as glGetTexImage or glTexSubImage2D).

I'm creating an App with editable images (basically an ms pain section). And attempting the following:

0) Setup all the openGL stuff (matrices, etc).
1) Create a 256x256 FBO (attach a depth storage and texture buffers).
2) Create a 256x256 texture for the image data. (initially empty)
3) Respond to user drawing input by:
3a)Bind FBO
3b)Bind Image Texture (from step 2) and render to the FBO
3c)Bind Point Sprite Texture (from step 0) and render point vertex array.
3d)glReadPixels the FBO data and update the ImageTexture (from step2)
4) Render the scene (bind backbuffer, clear, render bkg, render image texture).

Result: The first draw request works fine and the texture is updated with the new info and displays as expected.

Problem: All subsequent touches loose the previous data and only draw the new point(s).
Ex. I click at 250,250 and a point is drawn, then I click at 35,35 and the new point is drawn but the old point is lost.
--Note: I do see some stray pixels in the subsequent render calls.

Doing several glReadPixel calls during the drawing sequence. Revealed the following:

1) The FBO buffer has no data until the first set of point sprites is rendered (expected).
2) On subsequent passes the FBO has the previous data (expected).
3) After calling Clear on the FBO and rendering the ImageTexture (which should contain the data) the FBO data is empty! (unexpected)
-->This seems to be where the problem is coming in, but how can it be fixed? Is is not possible to render a texture to an FBO?

--Note: All the buffers were checked for completeness after they were created.

--Note: The FBO will be shared by many different texture drawing objects so it has to be cleared.

Here's some code from the draw to FBO methods discussed above:
(I omitted the code that generates the verts for the point sprites since it's definitely working).

//******** Grab the FBO
glBindTexture(GL_TEXTURE_2D, 0);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, myFBO);

glClearColor(0.0, 0.0, 0.0, 0.0); //clear it out first!
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glDisable(GL_BLEND);
glColor4f(1, 1, 1, 1); //needs full color!!
GLfloat tempVB[] = {0,0, 0,tw.texH, tw.texW,tw.texH, tw.texW,0,}; //theVerts buffer is already in use so need a temp!!
theTexC[0] = 0; theTexC[1] = 0;
theTexC[0] = 0; theTexC[1] = 1;
theTexC[0] = 1; theTexC[1] = 1;
theTexC[0] = 1; theTexC[1] = 0;

//CHECK FOR FLIPPING!!!!
if(tw.flipH){
theTexC[0] = 1; theTexC[4] = 0;
theTexC[2] = 1; theTexC[6] = 0;
}
if(tw.flipV){
theTexC[1] = 1; theTexC[5] = 0;
theTexC[3] = 0; theTexC[7] = 1;
}

glBindTexture(GL_TEXTURE_2D, tw.myTex); //bind the texture and RENDER!!
glVertexPointer(2, GL_FLOAT, 0, tempVB);
glTexCoordPointer(2, GL_FLOAT, 0, theTexC);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

//******** Render the Lines ( //Create the Verts and prepare the Data!!!
//Disable texture coord lists
glDisableClientState(GL_TEXTURE_COORD_ARRAY);

glBlendFunc(srcBlend, dstBlend);
glEnable(GL_BLEND);
glColor4f(texColor[0], texColor[1], texColor[2], texColor[3]);
glBindTexture(GL_TEXTURE_2D, brushTex.myTex);

glVertexPointer(2, GL_FLOAT, 0, theVerts);
glDrawArrays(GL_POINTS, 0, numValid);

//******** Grab the FBO data for the updated texture!
int texW = texH = 256; //hardcoded only for this example

GLubyte * tdata = calloc(tw.texW * tw.texH * 4, sizeof(GLubyte));
glReadPixels(0, 0, tw.texW, tw.texH, GL_RGBA, GL_UNSIGNED_BYTE, tdata);

glDeleteTextures(1, &myTex); myTex = 0; //kill original
glGenTextures(1, &myTex);
glBindTexture(GL_TEXTURE_2D, myTex);
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_RGBA, texW, texH, 0, GL_RGBA, GL_UNSIGNED_BYTE, tdata);

free(tdata);

//******** Set The Viewport back to normal
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
[self RenderScene];

DoubleJ
01-12-2010, 04:29 PM
Just to update the issue I also tried the following:

1) Create the Image Texture.
2) Create a new FBO and bind the Image Texture as the color buffer.
--Note: Obviously do not call clear here.
3) Render the point sprites

And this works as I need it to. Unfortunately this means creating a new FBO every time the size of the texture changes but I can live with it if there's no better way.

Note: I'll be using textures with sizes that are any combination of 32 to 256 (16 different combos) and with the limited iphone memory I can't see keeping all 16 sizes around in memory.