OpenGL渲染问题

时间:2010-08-26 05:33:05

标签: iphone objective-c opengl-es

(也在Apple Developer论坛上提问)

我似乎有OpenGL的渲染问题。当用户在屏幕上追踪他的手指时,我的应用程序应绘制一条线。因此,touchesMoved调用下面的draw函数并传递包含点数据的NSMutableArray currentStroke。

我遇到的问题是为每一行绘制的最后一个三角形(每行以touchesEnded结尾)闪烁。我认为它与渲染缓冲区有关...如果我从touchesEnded调用两次draw函数,则闪烁消失。我只是认为这是一个非常非常严格的解决方案。任何人都知道什么可能导致闪烁和解决方案?

- (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);

}

3 个答案:

答案 0 :(得分:1)

与问题没有直接关系,但是每次画画都会加载图片,不是吗? (或者可能不是,但我对Objective-c的语法感到困惑)如果你这样做,那不是一件好事。特别是initWithData:texData和glTexImage2D只能在draw()之外完成一次。

对于闪烁,它通常是双缓冲问题,但在iPhone上它始终是双缓冲区。

我认为你应该在实际的绘制调用之前调用glBindRenderbufferOES。

答案 1 :(得分:1)

哦,我得到了它。

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

所以你访问[currentStroke count] -1 + 1 - &gt;出界 for(int i = 0; i&lt;([currentStroke count] -2); i ++),并确保计数&gt; 2 ...

答案 2 :(得分:0)

当我想出来时应该发布这个,但迟到总比没有好。通过将kEAGLDrawablePropertyRetainedBacking设置为true,它会停止闪烁。当我刚刚使用glClear()一次(必须使用它两次)时,应用程序也闪烁,但设置保留的背景属性也固定了这一点。我还不完全确定闪烁发生的原因。这显然是一个双重缓冲问题,因为它在每一个框架上都闪烁着。