2010-07-29 2 views
2

iPhone에서 OpenGL ES로 포인트 스프라이트를 그리려고합니다. 가능한 많은 수 (1000), 최대 64 픽셀 (아마도 저의 문제가 바로 거기에 있습니다. 한계가 있습니까? 아니면 너무 많은 메모리를 사용할 수 있습니까?)왜 glClear()가 iPhone에서 포인트 스프라이트로 느린가요?

CADisplayLink를 사용하여 시간을 측정하고 있습니다. 프레임. 무슨 일이 생기면 첫 번째 그리기 기능은 포인트 카운트가 너무 높거나 포인트 크기가 너무 클 때 지연되거나 멈추는 경향이 있습니다. 아래 예제에서 glClear()는 첫 번째 드로잉 함수이며 0.02 초에서 0.2 초 사이에서 실행될 수 있습니다. glClear를 단순히 주석 처리하면 glDrawArrays가 느린 함수가됩니다 (그렇지 않으면 매우 빠르게 실행됩니다).

이 예제는 문제를 격리하기 위해 코드를 제거한 것입니다. 텍스처가없는 점 스프라이트를 같은 위치에 모두 그립니다. 모든 스프라이트 데이터 (위치, 색상, 크기)를 저장하기 위해 VBO를 사용하고 있습니다. 예를 들어 과잉으로 보일 수도 있지만 나중에이 데이터를 수정할 의도가 있습니다.

이것은 뷰의 init 함수 (마이너스 상용구 GL 설정) :

glDisable(GL_DEPTH_TEST); 
glDepthMask(GL_FALSE); 

glDisable(GL_LIGHTING); 
glDisable(GL_FOG); 

glEnable(GL_TEXTURE_2D); 
glEnable(GL_BLEND); 

glBlendEquationOES(GL_FUNC_ADD_OES); 

glClearColor(0.0, 0.0, 0.0, 0.0); 

glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 
glTexEnvi(GL_POINT_SPRITE_OES, GL_COORD_REPLACE_OES, GL_TRUE); 
glEnable(GL_POINT_SPRITE_OES); 

glEnableClientState(GL_VERTEX_ARRAY); 
glEnableClientState(GL_POINT_SIZE_ARRAY_OES); 
glEnableClientState(GL_COLOR_ARRAY); 

glBlendFunc(GL_SRC_ALPHA, GL_ONE); 

glEnable(GL_POINT_SMOOTH); 

glGenBuffers(1, &vbo);     // vbo is an instance variable 
glBindBuffer(GL_ARRAY_BUFFER, vbo); 

glMatrixMode(GL_PROJECTION); 
glOrthof(0.0, [self frame].size.width, 0.0, [self frame].size.height, 1.0f, -1.0f); 
glViewport(0, 0, [self frame].size.width, [self frame].size.height); 
glMatrixMode(GL_MODELVIEW); 

glTranslatef(0.0f, [self frame].size.height, 0.0f); 
glScalef(1.0f, -1.0f, 1.0f); 

그리고 이것은 렌더링 함수입니다 :

- (void)render 
{ 
    glClear(GL_COLOR_BUFFER_BIT); // This function runs slowly! 

    int pointCount = 1000; 

    // fyi... 
    // typedef struct { 
    // CGPoint point; 
    // CFTimeInterval time; 
    // GLubyte r, g, b, a; 
    // GLfloat size; 
    // } MyPoint; 

    glBufferData(GL_ARRAY_BUFFER, sizeof(MyPoint)*pointCount, NULL, GL_DYNAMIC_DRAW); 
    MyPoint * vboBuffer = (MyPoint *)glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES); 

    for (int i = 0; i < pointCount; i++) { 
     vboBuffer[i].a = (GLubyte)0xFF; 
     vboBuffer[i].r = (GLubyte)0xFF; 
     vboBuffer[i].g = (GLubyte)0xFF; 
     vboBuffer[i].b = (GLubyte)0xFF; 
     vboBuffer[i].size = 64.0; 
     vboBuffer[i].point = CGPointMake(200.0, 200.0); 
    } 

    glUnmapBufferOES(GL_ARRAY_BUFFER); 

    glPointSizePointerOES(GL_FLOAT, sizeof(MyPoint), (void *)offsetof(MyPoint, size)); 
    glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(MyPoint), (void *)offsetof(MyPoint, r)); 
    glVertexPointer(2, GL_FLOAT, sizeof(MyPoint), (void *)offsetof(MyPoint, point)); 

    glDrawArrays(GL_POINTS, 0, pointCount); 

    [context presentRenderbuffer:GL_RENDERBUFFER_OES]; 
} 

왜 glClear 기능 실속이가? 그것은 단지 무작위로 지연되지 않습니다 - 포인트 수나 크기에 따라, 그것은 같은 intevals (예 : 0.015 초, 0.030 초, 0.045 초 등)에서 임의로 지연되는 경향이 있습니다. 또한 뭔가 이상한 내가 glBlendMode (GL_ZERO, GL_ONE)로 전환하면, 잘 (비록 이것이 이후의 시각 효과가 아닐지라도) 잘 실행된다는 것입니다. 다른 glBlendMode 값도 속도를 변경합니다. 일반적으로 속도가 향상됩니다. VBO와는 아무런 관련이 없기 때문에 메모리 문제가 아니라고 생각합니다.

나는 OpenGL에서 약간 새로운 것으로 인정하며 VBO 나 다른 것들에 대한 기본 개념을 오해 할 수도있다. 어떤 도움이나지도가 크게 감사드립니다!

답변

0

glClear()이 느리면 뷰포트 영역을 완전히 덮는 큰 빈 쿼드를 그릴 수 있습니다.

+0

나는 이것을 시도해 보았지만 정말로 glClear가 느린 것처럼 보였습니다. 첫 번째 그리기 기능이 무엇이든간에 나타납니다. glClear를 없애고 대신 빈 쿼드를 그리면 glDrawArrays()에서 속도가 느려집니다. –

0

동기화를 사용하고 있습니까? (또는 활성화되어 있습니까?) 보고있는 지연은 CPU와 GPU가 병렬로 실행된다는 사실과 관련이 있으므로 개별 GL 호출의 시간을 측정하는 것은 의미가 없습니다.

VSync를 사용 중이거나 GPU가 과도하게로드되어있는 경우 SwapBuffers 호출에 대기 시간이있을 수 있습니다. 일부 드라이버는 VBlank를 대기하기 위해 바쁜 루프를 만들기 때문입니다.

먼저 GL 호출을 개별적으로 수행하면 안됩니다. 대부분의 GL 호출은 GPU의 일부 상태를 설정하거나 명령 버퍼에 기록하기 때문에 명령 실행은 비동기 적으로 발생합니다.

+0

개별 GL 호출을 타이밍하지 않는 것이 맞습니다. 아마도 천천히 실행되는 동일한 함수가 일관성있게 작동하지 않는 이유 일 수 있습니다. 그러나이 문제로 인해 FPS가 대폭 감소 (때로는 15fps로 낮아짐)하여 실행 시간을 측정하는 데 오류가 발생하지 않습니다. VSync를 명시 적으로 활성화하거나 비활성화하지 않았습니다. 이 일이 내가해야 할 일인가? –

관련 문제