2011-01-27 5 views
10

저는 현재 물리 시뮬레이션을 iPhone 자체의 비디오로 변환하는 프로젝트를 진행하고 있습니다.OpenGL to iPhone on

이렇게하려면 두 개의 다른 루프를 사용하고 있습니다. 첫 번째 루프는 AVAssetWriterInput 개체가 더 많은 이미지를 얻기 위해 EAGLView를 폴링하는 블록에서 실행됩니다. EAGLView는 저장되어있는 배열의 이미지를 제공합니다.

다른 루프가 실제 시뮬레이션입니다. 나는 시뮬레이션 타이머를 끄고 때마다 사전 지정된 시간차로 직접 진드기를 호출합니다. 틱이 호출 될 때마다 버퍼가 스왑 된 후 EAGLView의 스왑 버퍼 메서드에서 새 이미지를 만듭니다. 이 이미지는 AVAssetWriter가 폴링하는 배열에 저장됩니다.

가 배열이

이 모든 너무 크게하지 않도록 잘 작동 할 몇 가지 기타 코드도하지만, 매우 매우 느립니다.

내가하는 일은 개념적으로 전체 프로세스의 속도를 느리게 할 수 있습니까? 또한 누구나 glReadPixels보다 Open GL에서 이미지를 얻는 더 빠른 방법을 알고 있습니까?

+0

무엇보다도 가장 많은 시간이 걸리는 함수 호출을 증명하기 위해 Instruments (Time Profiler, Shark)를 사용 해본 적이 있습니까? – makdad

답변

3

비디오 메모리는 쓰기가 빠르며 읽기가 느리다. 그래서 텍스쳐로 렌더링을 수행합니다. '물론

-(TextureInf*) makeSceneSnapshot { 
    // create texture frame buffer 
    GLuint textureFrameBuffer, sceneRenderTexture; 

    glGenFramebuffersOES(1, &textureFrameBuffer); 
    glBindFramebufferOES(GL_FRAMEBUFFER_OES, textureFrameBuffer); 

    // create texture to render scene to 
    glGenTextures(1, &sceneRenderTexture); 
    glBindTexture(GL_TEXTURE_2D, sceneRenderTexture); 

    // create TextureInf object 
    TextureInf* new_texture = new TextureInf(); 
    new_texture->setTextureID(sceneRenderTexture); 
    new_texture->real_width = [self viewportWidth]; 
    new_texture->real_height = [self viewportHeight]; 

    //make sure the texture dimensions are power of 2 
    new_texture->width = cast_to_power(new_texture->real_width, 2); 
    new_texture->height = cast_to_power(new_texture->real_height, 2); 

    //AABB2 = axis aligned bounding box (2D) 
    AABB2 tex_box; 

    tex_box.p1.x = 1 - (GLfloat)new_texture->real_width/(GLfloat)new_texture->width; 
    tex_box.p1.y = 0; 
    tex_box.p2.x = 1; 
    tex_box.p2.y = (GLfloat)new_texture->real_height/(GLfloat)new_texture->height; 
    new_texture->setTextureBox(tex_box); 

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, new_texture->width, new_texture->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); 
    glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, sceneRenderTexture, 0); 

    // check for completness 
    if(glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) { 
     new_texture->release(); 
     @throw [NSException exceptionWithName: EXCEPTION_NAME 
             reason: [NSString stringWithFormat: @"failed to make complete framebuffer object %x", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES)] 
            userInfo: nil]; 
     new_texture = nil; 
    } else { 
     // render to texture 
     [self renderOneFrame]; 
    } 

    glDeleteFramebuffersOES(1, &textureFrameBuffer); 

    //restore default frame and render buffers 
    glBindFramebufferOES(GL_FRAMEBUFFER_OES, _defaultFramebuffer); 
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, _colorRenderbuffer); 
    glEnable(GL_BLEND);   
    [self updateViewport];  
    glMatrixMode(GL_MODELVIEW); 


    return new_texture; 
} 

, 당신 경우 : 여기 텍스처 장면 렌더링에 만든 전체 방법입니다 (일부 사용자 지정 컨테이너가,하지만 나는 그것이 자신으로 대체 할 매우 간단하다고 생각) 스냅 샷을 항상 수행하면 텍스처 프레임을 만들고 렌더링 버퍼를 한 번만 (그리고 메모리를 할당하는 것이 좋습니다.

1

GPU는 CPU에서 비동기 적으로 실행되므로 렌더링을 마친 직후에 glReadPixels를 실행하려고하면 명령이 GPU로 플러시되고 렌더링되기를 기다려야합니다 그들을 다시 읽을 수 있습니다.

동기식으로 대기하는 대신 스냅 샷을 텍스처 대기열에 렌더링합니다 (Max와 같은 FBO 사용). 이전 프레임 중 하나를 deque하기 전에 두 개 이상의 프레임을 렌더링 할 때까지 기다리십시오. iPhone이 울타리 또는 객체 동기화를 지원하는지 여부는 알 수 없지만, 그렇다면 픽셀을 읽기 전에 렌더링이 완료되었는지 확인할 수 있습니다.

1

CADisplayLink 개체를 사용하여 드로잉 속도와 캡처 속도가 장치의 화면 재생 빈도와 일치하는지 확인할 수 있습니다. 장치 화면 새로 고침 당 너무 많은 시간을 새로 고침하고 캡처하여 실행 루프의 실행 시간을 느리게 할 수 있습니다.

앱의 목표에 따라 현재 표시된 모든 프레임을 캡처 할 필요가 없을 수도 있으므로 선택기에서 현재 프레임을 캡처할지 여부를 선택할 수 있습니다. 문제는 새로운 것은 아니지만

0

,

glReadPixels 실제로 매우 느립니다. 그래서 나는에 던질 줄 알았는데 아직 대답 아니에요, 따라서 adversly없이 OpenGL에 응용 프로그램에서 비디오를 녹화 할 수 없습니다 성능에 영향을줍니다.

해결 방법을 찾았으며 성능 손실없이 OpenGL 기반 그래픽을 비디오 파일에 기록 할 수있는 Everyplay라는 무료 SDK를 만들었습니다.https://developers.everyplay.com/