2012-06-11 4 views
3

이미지 조작을 위해 Brad Larson's wonderful GPUImage library을 사용 중입니다. 지금까지는 훌륭했습니다. 그러나 메쉬 변형을 허용하는 필터를 추가하고 꽤 많은 문제가 발생합니다. 특히, VBO를 사용하여 쿼드를 렌더링하는 필터를 사용하여 궁극적으로 변형의 정점을 변경할 수 있습니다.iOS : GPUImage 라이브러리 및 VBO

VBO를 사용하는 첫 번째 단계에서 충돌이 발생합니다.

하위 클래스를 생성하여 - (void)newFrameReadyAtTime:(CMTime)frameTime 메서드를 재정 의하여 VBO를 통해 쿼드를 렌더링했습니다. 참고 : 풀 메쉬가 아닌 단일 쿼드를 렌더링하려하고 있으므로 한 번에 하나의 문제 만 해결할 수 있습니다.

@implementation GPUMeshImageFilter { 
    GLuint _positionVBO; 
    GLuint _texcoordVBO; 
    GLuint _indexVBO; 

    BOOL isSetup_; 
} 

- (void)setupBuffers 
{ 
    static const GLsizeiptr verticesSize = 4 * 2 * sizeof(GLfloat); 
    static const GLfloat squareVertices[] = { 
     -1.0f, -1.0f, 
     1.0f, -1.0f, 
     -1.0f, 1.0f, 
     1.0f, 1.0f, 
    }; 

    static const GLsizeiptr textureSize = 4 * 2 * sizeof(GLfloat); 
    static const GLfloat squareTextureCoordinates[] = { 
     0.0f, 0.0f, 
     1.0f, 0.0f, 
     0.0f, 1.0f, 
     1.0f, 1.0f, 
    }; 

    static const GLsizeiptr indexSize = 4 * sizeof(GLushort); 
    static const GLushort indices[] = { 
     0,1,2,3, 
    }; 

    glGenBuffers(1, &_indexVBO); 
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexVBO); 
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexSize, indices, GL_STATIC_DRAW); 

    glGenBuffers(1, &_positionVBO); 
    glBindBuffer(GL_ARRAY_BUFFER, _positionVBO); 
    glBufferData(GL_ARRAY_BUFFER, verticesSize, squareVertices, GL_STATIC_DRAW); 

    glEnableVertexAttribArray(0); 
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2*sizeof(GLfloat), 0); 

    glGenBuffers(1, &_texcoordVBO); 
    glBindBuffer(GL_ARRAY_BUFFER, _texcoordVBO); 
    glBufferData(GL_ARRAY_BUFFER, textureSize, squareTextureCoordinates, GL_DYNAMIC_DRAW); 

    glEnableVertexAttribArray(1); 
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2*sizeof(GLfloat), 0); 

    NSLog(@"Setup complete"); 
} 

- (void)newFrameReadyAtTime:(CMTime)frameTime; 
{ 
    if (!isSetup_) { 
     [self setupBuffers]; 
     isSetup_ = YES; 
    } 

    if (self.preventRendering) 
    { 
     return; 
    } 

    [GPUImageOpenGLESContext useImageProcessingContext]; 
    [self setFilterFBO]; 

    [filterProgram use]; 

    glClearColor(backgroundColorRed, backgroundColorGreen, backgroundColorBlue, backgroundColorAlpha); 
    glClear(GL_COLOR_BUFFER_BIT); 

    glActiveTexture(GL_TEXTURE2); 
    glBindTexture(GL_TEXTURE_2D, filterSourceTexture); 

    glUniform1i(filterInputTextureUniform, 2); 

    if (filterSourceTexture2 != 0) 
    { 
     glActiveTexture(GL_TEXTURE3); 
     glBindTexture(GL_TEXTURE_2D, filterSourceTexture2); 

     glUniform1i(filterInputTextureUniform2, 3); 
    } 

    NSLog(@"Draw VBO"); 
    glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0); 

    [self informTargetsAboutNewFrameAtTime:frameTime]; 
} 

@end 

이 필터를 연결하면 "설치 완료"및 "VBO 그리기"가 콘솔에 표시됩니다. 그러나 대상 (이 경우 GPUImageView)을 호출 한 후 glDrawArrays을 사용하는 대상의 그리기 호출에서 충돌합니다.

glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 

다음은이 행을 포함하는 완전한 방법입니다.

- (void)newFrameReadyAtTime:(CMTime)frameTime; 
{ 
    [GPUImageOpenGLESContext useImageProcessingContext]; 
    [self setDisplayFramebuffer]; 

    [displayProgram use]; 

    glClearColor(backgroundColorRed, backgroundColorGreen, backgroundColorBlue, backgroundColorAlpha); 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

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

    glActiveTexture(GL_TEXTURE4); 
    glBindTexture(GL_TEXTURE_2D, inputTextureForDisplay); 
    glUniform1i(displayInputTextureUniform, 4); 

    glVertexAttribPointer(displayPositionAttribute, 2, GL_FLOAT, 0, 0, imageVertices); 
    glVertexAttribPointer(displayTextureCoordinateAttribute, 2, GL_FLOAT, 0, 0, textureCoordinates); 

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 

    [self presentFramebuffer]; 
} 

어떤 도움을 주시면 감사하겠습니다. 잠시 머리를 숙였습니다.

답변

2

GPUImageView-newFrameReadyAtTime:이 실행될 때 GL_ARRAY_BUFFER이 여전히 바인딩되어 있기 때문에 충돌이 발생할 가능성이 있습니다.

(즉 0에 결합) 버퍼를 바인딩 해제 -setupBuffers 끝에보십시오

glBindBuffer(GL_ARRAY_BUFFER, 0); 

GPUImage 하나 GPUImageInput (예 GPUImageFilter, GPUImageView에서 동일한 OpenGL은 콘텍스트를 사용하기 때문에 이것은 문제 이유는) 다음에. 나는 각 단계가 OpenGL 텍스처로 출력 된 다음 그 텍스처를 다음에 직접 사용할 수 있도록하기 위해서 크게 믿는다. GPUImageInput. GL_ARRAY_BUFFER 여전히 효과적으로 포인트를 무의미과 충돌을 일으킬 가능성이 imageVertices의 오프셋에서 인구가 VBO에 displayPositionAttribute 속성을 시도, glVertexAttribPointerGPUImageView-newFrameReadyAtTime 내부 변화의 동작을 바인딩 그래서 때문에

. glVertexAttribPointer docs을 참조하십시오.

0

이 코드는 나에게 전혀 적합하지 않습니다. 버텍스 속성 배열 4 & 5를 활성화하는 이유는 무엇입니까? 사용할 속성 위치에서 배열을 활성화해야합니다. 정점 속성이 위치 0에있는 경우

//position vbo 
glEnableVertexAttribArray(4); 
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2*sizeof(GLfloat), 0); 

//texcoord vbo 
glEnableVertexAttribArray(5); 
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2*sizeof(GLfloat), 0); 

, 당신은 그것 (I 의심) 위치 4에 있다면 다음 ATTRIB 4를 사용하도록 설정해야합니다, ATTRIB 0에 대한 ATTRIB 0으로 설정 포인터를 활성화하기위한 포인터를 설정해야합니다 포지션 4. 당신이 가지고있는 것처럼 그것이 어긋나는 이유가 무엇인지 생각할 수 없습니다.

레이아웃 속성을 통해 설정하거나 쉐이더를 연결하기 전에 glBindAttribLocation을 사용하거나 연결 한 후에 glGetAttribLocation을 사용하여 올바른 위치를 지정해야합니다.

이 말이 맞지 않으면 알려주세요.

+0

죄송합니다. 붙여 넣기위한 것이 아닙니다. 나는 몇 가지 일로 어지럽 혔다. 원래 원래 0과 1이었습니다. 게시물 수정 중입니다. – MarkPowell