iOS:GPUImage 库和 VBO
Posted
技术标签:
【中文标题】iOS:GPUImage 库和 VBO【英文标题】:iOS: GPUImage Library and VBO 【发布时间】:2012-06-11 13:34:33 【问题描述】:我正在使用Brad Larson's wonderful GPUImage library 进行图像处理。到目前为止,一切都很好。但是,我正在尝试添加一个过滤器以允许网格变形并遇到很多问题。具体来说,我想要一个使用 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”显示到控制台。但是,在它调用目标(在本例中为 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];
任何帮助将不胜感激,我一直在努力解决这个问题。
【问题讨论】:
【参考方案1】:看起来很可能发生了崩溃,因为GL_ARRAY_BUFFER
在执行GPUImageView-newFrameReadyAtTime:
时仍然绑定。
尝试在-setupBuffers
的末尾取消绑定缓冲区(即绑定到0
):
glBindBuffer(GL_ARRAY_BUFFER, 0);
这是一个问题的原因是因为 GPUImage 从一个 GPUImageInput
(例如GPUImageFilter
、GPUImageView
)到下一个使用相同的 OpenGL 上下文。我相信很大程度上是为了每一步都可以输出到一个 OpenGL 纹理,然后将该纹理直接提供给下一个GPUImageInput
。
因此,由于GL_ARRAY_BUFFER
仍然绑定glVertexAttribPointer
在GPUImageView-newFrameReadyAtTime
中的行为发生变化,因此有效地尝试将displayPositionAttribute
属性指向填充的VBO,偏移量为imageVertices
,这是荒谬的并且可能导致崩溃。请参阅glVertexAttribPointer docs。
【讨论】:
【参考方案2】:下面的这段代码对我来说根本不合适。为什么要启用顶点属性数组 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
。
如果这没有意义,请告诉我。
【讨论】:
对不起,这不是要粘贴的。我在捣乱一些事情。原来,原来是0和1。立即修复帖子。以上是关于iOS:GPUImage 库和 VBO的主要内容,如果未能解决你的问题,请参考以下文章
iOS中开源框架GPUImage的使用之生成libGPUImage.a文件和创建工程
IOS OpenGL ES GPUImage GPUImageWeakPixelInclusionFilter
IOS OpenGL ES GPUImage 彩色模糊 GPUImageRGBOpeningFilter