3

私はブラッドラーソンの素晴らしいGPUImageライブラリを画像操作に利用しています。これまでのところ、それは素晴らしかったです。ただし、メッシュの変形を可能にするフィルターを追加しようとしていますが、かなりの問題が発生しています。具体的には、VBOを使用してクワッドをレンダリングするフィルターが必要です。これにより、最終的に変形の頂点を動的に変更できます。

VBOを使用する最初のステップは、クラッシュを引き起こすことです。

VBOを介してクワッドをレンダリングするメソッドをGPUImageFilterオーバーライドするサブクラスを作成しました。:フルメッシュではなく、単一のクワッドをレンダリングしようとしているだけです。そうすれば、一度に1つの問題に取り組むことができます。- (void)newFrameReadyAtTime:(CMTime)frameTime

@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];
}

どんな助けでも大歓迎です、私はしばらくの間これに頭をぶつけてきました。

4

2 に答える 2

2

実行GL_ARRAY_BUFFER時にまだバインドされているため、クラッシュが発生する可能性があります。GPUImageView-newFrameReadyAtTime:

0の最後でバッファのバインドを解除してみてください(つまり、にバインドしてください)。-setupBuffers

glBindBuffer(GL_ARRAY_BUFFER, 0);

これが問題になる理由は、GPUImageが1つGPUImageInput(たとえばGPUImageFilterGPUImageView)から次へと同じOpenGLコンテキストを使用するためです。私は主に、各ステップがOpenGLテクスチャに出力し、そのテクスチャを次のステップで直接利用できるようにするためだと信じていますGPUImageInput

したがって、内部変更GL_ARRAY_BUFFERの動作はまだバインドされているため、属性を設定されたVBOのオフセットで効果的にポイントしようとします。これは無意味であり、クラッシュを引き起こす可能性があります。glVertexAttribPointerのドキュメントを参照してください。glVertexAttribPointerGPUImageView-newFrameReadyAtTimedisplayPositionAttributeimageVertices

于 2012-09-25T05:47:37.717 に答える
0

以下のこのコードは、私にはまったく正しく見えません。頂点属性配列4および5を有効にするのはなぜですか?使用する属性の場所でアレイを有効にする必要があります。

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

頂点属性が位置0にある場合は、属性0を有効にして、属性0のポインターを設定する必要があります。位置4にある場合(これは疑わしいです)、属性4を有効にして、位置4のポインターを設定する必要があります。あなたがそれを持っているようにそれがミスマッチであるべきである理由を考えてください。

レイアウト属性を介して設定するか、glBindAttribLocationシェーダーリンクの前に使用するかglGetAttribLocation、リンク後にを使用して、適切な位置を取得する必要があります。

これが意味をなさない場合はお知らせください。

于 2012-06-12T05:28:51.213 に答える