another question about OpenGL ES rendering to texture
- by ensoreus
Hello, pros and gurus!
Here is another question about rendering to texture.
The whole stuff is all about saving texture between passing image into different filters. Maybe all iPhone developers knows about Apple's sample code with OpenGL processing where they used GL filters(functions), but pass into them the same source image. I need to edit an image by passing it sequentelly with saving the state of the image to edit. I am very noob in OpenGL, so I spent increadibly a lot of to solve the issue.
So, I desided to create 2 FBO's and attach source image and temporary image as a textures to render in.
Here is my init routine:
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnable(GL_TEXTURE_2D);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glGetIntegerv(GL_FRAMEBUFFER_BINDING_OES, (GLint *)&SystemFBO);
glImage = [self loadTexture:preparedImage]; //source image
for (int i = 0; i < 4; i++)
{
fullquad[i].s *= glImage->s;
fullquad[i].t *= glImage->t;
flipquad[i].s *= glImage->s;
flipquad[i].t *= glImage->t;
}
tmpImage = [self loadEmptyTexture]; //editing image
glGenFramebuffersOES(1, &tmpImageFBO);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, tmpImageFBO);
glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, tmpImage->texID, 0);
GLenum status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES);
if(status != GL_FRAMEBUFFER_COMPLETE_OES) {
NSLog(@"failed to make complete tmp framebuffer object %x", status);
}
glBindTexture(GL_TEXTURE_2D, 0);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
glGenRenderbuffersOES(1, &glImageFBO);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, glImageFBO);
glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, glImage->texID, 0);
status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) ;
if(status != GL_FRAMEBUFFER_COMPLETE_OES) {
NSLog(@"failed to make complete cur framebuffer object %x", status);
}
glBindTexture(GL_TEXTURE_2D, 0);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
When user drag the slider, this routine invokes to apply changes
-(void)setContrast:(CGFloat)value{
contrast = value;
if(flag!=mfContrast){
NSLog(@"contrast: dumped");
flag = mfContrast;
glBindFramebufferOES(GL_FRAMEBUFFER_OES, glImageFBO);
glClearColor(1,1,1,1);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrthof(0, 512, 0, 512, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glScalef(512, 512, 1);
glBindTexture(GL_TEXTURE_2D, tmpImage->texID);
glViewport(0, 0, 512, 512);
glVertexPointer(2, GL_FLOAT, sizeof(V2fT2f), &fullquad[0].x);
glTexCoordPointer(2, GL_FLOAT, sizeof(V2fT2f), &fullquad[0].s);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
}
glBindFramebufferOES(GL_FRAMEBUFFER_OES,tmpImageFBO);
glClearColor(0,0,0,1);
glClear(GL_COLOR_BUFFER_BIT);
glEnable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrthof(0, 512, 0, 512, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glScalef(512, 512, 1);
glBindTexture(GL_TEXTURE_2D, glImage->texID);
glViewport(0, 0, 512, 512);
[self contrastProc:fullquad value:contrast];
glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
[self redraw];
}
Here are two cases: if it is the same filter(edit mode) to use, I bind tmpFBO to draw into tmpImage texture and edit glImage texture. contrastProc is a pure routine from Apples's sample. If it is another mode, than I save edited image by drawing tmpImage texture in source texture glImage, binded with glImageFBO. After that I call redraw:
glBindFramebufferOES(GL_FRAMEBUFFER_OES, SystemFBO);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrthof(0, kTexWidth, 0, kTexHeight, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glScalef(kTexWidth, kTexHeight, 1);
glBindTexture(GL_TEXTURE_2D, glImage->texID);
glViewport(0, 0, kTexWidth, kTexHeight);
glVertexPointer(2, GL_FLOAT, sizeof(V2fT2f), &flipquad[0].x);
glTexCoordPointer(2, GL_FLOAT, sizeof(V2fT2f), &flipquad[0].s);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
And here it binds visual framebuffer and dispose glImage texture.
So, the result is VERY aggresive filtering. Increasing contrast volume by just 0.2 brings image to state that comparable with 0.9 contrast volume in Apple's sample code project. I miss something obvious, I guess. Interesting, if I disabple line
glBindTexture(GL_TEXTURE_2D, glImage->texID);
in setContrast routine it brings no effect. At all. If I replace tmpImageFBO with SystemFBO to draw glImage directly on display(and disabling redraw invoking line), all works fine.
Please, HELP ME!!! :(