3

我正在使用Brad Larson 出色的 GPUImage 库进行图像处理。到目前为止,一切都很好。但是,我正在尝试添加一个过滤器以允许网格变形并遇到很多问题。具体来说,我想要一个使用 VBO 渲染四边形的过滤器,这样我最终可以动态地更改顶点以进行变形。

使用 VBO 的第一步是导致崩溃。

我创建了一个GPUImageFilter重写该- (void)newFrameReadyAtTime:(CMTime)frameTime方法的子类,以通过 VBO 呈现四边形。注意:我只是尝试渲染单个 Quad 而不是完整的网格,这样我可以一次解决一个问题。

@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”显示在控制台上。但是,在它调用目标(在本例中为 a 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 从一个GPUImageInput(例如GPUImageFilterGPUImageView)到另一个使用相同的 OpenGL 上下文。我相信主要是为了每个步骤都可以输出到 OpenGL 纹理,然后让该纹理直接提供给下一个GPUImageInput.

因此,由于GL_ARRAY_BUFFER仍然绑定了glVertexAttribPointer内部GPUImageView-newFrameReadyAtTime更改的行为,因此有效地尝试将displayPositionAttribute属性指向偏移量为 的填充 VBO imageVertices,这是无意义的并且可能导致崩溃。请参阅glVertexAttribPointer 文档

于 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 回答