简体   繁体   中英

OpenGL render issue

(Also asked on the Apple Developer forums)

I seem to have a rendering issue with OpenGL. My app is supposed to draw a line as the user traces his finger across the screen. So, touchesMoved calls the draw function below and passes a NSMutableArray currentStroke which contains point data.

The issue I am having is that the last triangle drawn for each line (each line ends with touchesEnded) flickers. I think it has to do with the render buffer... If I call the draw function twice from touchesEnded, the flickering goes away. I just think that is a very, very jimmy-rigged solution. Anyone have an idea of what could cause the flickering and a solution?

- (void)draw {

glLoadIdentity();

//Configuring OpenGL
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);



//Texture Loading
GLuint      texture[1];
glGenTextures(1, &texture[0]);
glBindTexture(GL_TEXTURE_2D, texture[0]);

//Configuring Image for OpenGL Texture: Switch off mipmap; Set linear scaling
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); 
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);

//Set image to texture
NSString *path = [[NSBundle mainBundle] pathForResource:@"at2" ofType:@"png"];
    NSData *texData = [[NSData alloc] initWithContentsOfFile:path];
    UIImage *image = [[UIImage alloc] initWithData:texData];
    if (image == nil)
        NSLog(@"No Image");

    GLuint width = CGImageGetWidth(image.CGImage);
    GLuint height = CGImageGetHeight(image.CGImage);
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    void *imageData = malloc( height * width * 4 );
    CGContextRef context2 = CGBitmapContextCreate( imageData, width, height, 8, 4 * width, colorSpace, kCGImageAlphaPremultipliedLast |kCGBitmapByteOrder32Big );
    CGColorSpaceRelease( colorSpace );
    CGContextClearRect( context2, CGRectMake( 0, 0, width, height ) );
    CGContextTranslateCTM( context2, 0, height - height );
    CGContextDrawImage( context2, CGRectMake( 0, 0, width, height ), image.CGImage );

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);

    CGContextRelease(context2);

    free(imageData);
    [image release];
    [texData release];

static const GLfloat texCoords[] = {
        0.0, 1.0,
        1.0, 1.0,
        1.0, 0.0,
        0.0, 0.0
 };




glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

GLfloat vertices[8];
GLfloat xadjust;
GLfloat yadjust;

//Iterate through points and create triangles

if ( (currentStroke != nil) && ([currentStroke count] > 1)) {

  for (int i=0; i<([currentStroke count]-1); i++) {
    vertices[0] = [[currentStroke objectAtIndex:i] CGPointValue].x;
    vertices[1] = self.frame.size.height - [[currentStroke objectAtIndex:i] CGPointValue].y;
    vertices[2] = [[currentStroke objectAtIndex:i+1] CGPointValue].x;
    vertices[3] = self.frame.size.height - [[currentStroke objectAtIndex:i+1] CGPointValue].y;

    //Minimum width of triangle
    xadjust = -4;


    //Minimum height of triangle, increase of y aspect of triangle is short
    if ((vertices[3]-vertices[1])<1&&(vertices[3]-vertices[1])>=0) {
      yadjust = 2;
    } else if ((vertices[3]-vertices[1])>-1&&(vertices[3]-vertices[1])<=0){ 
      yadjust = -3;
    } else  {
      yadjust = 2;
    }

    vertices[4] = [[currentStroke objectAtIndex:i] CGPointValue].x+xadjust;
    vertices[5] = self.frame.size.height - [[currentStroke objectAtIndex:i] CGPointValue].y+yadjust;
    vertices[6] = [[currentStroke objectAtIndex:i+1] CGPointValue].x+xadjust;
    vertices[7] = self.frame.size.height - [[currentStroke objectAtIndex:i+1] CGPointValue].y+yadjust;

    glTexCoordPointer(2, GL_FLOAT, 0, texCoords);

    glVertexPointer(2, GL_FLOAT, 0, vertices);

    glEnableClientState(GL_VERTEX_ARRAY);

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);


  }




  glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
  [context presentRenderbuffer:GL_RENDERBUFFER_OES];


  glDisable(GL_BLEND);
  glDisableClientState(GL_VERTEX_ARRAY);
  glDisableClientState(GL_NORMAL_ARRAY);
  glDisableClientState(GL_TEXTURE_COORD_ARRAY);

}

Not directly related to the question, but you load the image each and every time you draw, don't you ? (or maybe not, but I'm puzzled by objective-c's syntax) If you do, it's not a good thing. Especially initWithData:texData and glTexImage2D should be done only once, outside draw().

For the flickering, it's usually a double-buffering issue, but on iPhone it's always a double-buffer.

I think you should call glBindRenderbufferOES before the actual draw calls, though.

oh, I thing I got it.

for (int i=0; i<([currentStroke count]-1); i++)
    vertices[2] = [[currentStroke objectAtIndex:i+1] CGPointValue].x;

so you access [currentStroke count] -1 +1 -> out of bounds for (int i=0; i<([currentStroke count]-2); i++), and make sure count > 2...

Should have posted this when I figured it out, but better late than never. By setting kEAGLDrawablePropertyRetainedBacking to true, it stopped flickering. The app also flickered when I just used glClear() once (had to use it twice), but setting the retained background property fixed this as well. I'm still not entirely sure why the flickering happened. It was obviously a double buffer issue since it flickered on every other frame.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM