使用GLKit openGL - iOS绘制YUV图像

时间:2013-09-18 14:34:31

标签: ios opengl-es rendering glkit

我想在iOS设备上渲染yuv图像。我认为可以使用openGL来实现。 (实际上我必须连续渲染多个这样的图像)

我理解的是,GLKit是iOS创建的一个抽象,其中有一个GLKView,它将拥有并处理渲染缓冲区。我目前正在尝试使用GLKViewController,并且正在使用所需的fps成功完成帧更新。我通过使用glClear函数调用来符合。

现在的任务是在视图上渲染图像。

有一个类GLKBaseEffect,它将具有基本着色器。我无法确定要设置的属性,因此我只需创建它并在每次渲染之前调用prepareToDraw

有一个用于处理纹理的类GLKTextureLoader,但在我看来它只适用于Quartz图像,即yuv420 plane无法使用此类加载到纹理中。

// create the texture
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8,  width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, [imageNSData bytes]);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);  

我使用此代码生成纹理并绑定它,但我真的不知道我在这里尝试做什么。无论它是什么,它都不会在屏幕上显示任何图像,我不知道下一步该做什么。

我没有创建任何着色器,假设baseEffect会有一些东西。

这个https://developer.apple.com/library/ios/documentation/3DDrawing/Conceptual/OpenGLES_ProgrammingGuide/WorkingwithEAGLContexts/WorkingwithEAGLContexts.html#//apple_ref/doc/uid/TP40008793-CH103-SW8告诉我,我必须使用EAGLayer在屏幕上渲染图像。

我可以使用GLKit渲染图像吗?如果是,我们是否有任何不使用GLKTextureLoader类的示例代码或教程(我找不到)?如果没有,是否有类似的使用EAGLLayer渲染的教程(到目前为止我还没有探讨过它)?

1 个答案:

答案 0 :(得分:4)

听起来你真的在这里询问几个不同的主题:

  • 如何使用GLKView vs CAEAGLLayer
  • 进行绘制
  • GLKBaseEffectGLKTextureLoader如何适用于一般的OpenGL ES绘图
  • 如果有一个
  • ,如何绘制纹理
  • 如何渲染YUV图像数据

我会尝试依次解决每个问题......


GLKView对于您想要做的任何OpenGL ES绘图都很好 - 它会为您链接的旧文档执行所有操作(为您设置帧缓冲区,CAEAGLLayer等)你不必编写那段代码。在GLKView绘图方法(drawRect:glkView:drawInRect:内,取决于您是在绘制子类还是委托),您可以编写与{{1}相同的OpenGL ES绘图代码(或任何其他系统)。


您可以相互独立地使用CAEAGLLayerGLKViewGLKTextureLoader。如果您想编写所有自己的绘图代码并使用自己的着色器,则可以使用GLKBaseEffect绘制而不使用GLKView。 (您甚至可以混合和匹配GLKBaseEffect和您自己的东西,就像您在使用OpenGL游戏模板创建新的Xcode项目时所看到的那样。)同样,GLKBaseEffect加载图像数据并吐出{{1} 1}}您需要将其绑定以进行绘制,无论您是否使用GLKTextureLoader绘制它,都可以使用它。


获得纹理后,无论是通过name还是自己读取/解码数据并将其提供给GLKBaseEffect,都可以使用三个基本步骤进行绘制:

  1. 使用GLKTextureLoader绑定纹理名称。
  2. 绘制一些要纹理化的几何体(使用glTexImage2DglBindTexture或类似物)
  3. 使用片段着色器查找纹素并输出颜色。
  4. 如果您只想绘制填充视图的图像,只需绘制四边形(两个三角形)。这是我用来设置一个四边形的顶点数组对象的代码,当我想绘制全屏时:

    glDrawArrays

    然后,绘制它:

    glDrawElements

    这只是几何绘图部分。将其与typedef struct __attribute__((packed)) { GLKVector3 position; GLKVector2 texcoord; } Vertex; static Vertex vertexData[] = { {{-1.0f, 1.0f, -1.0f}, {0.0f, 0.0f}}, {{-1.0f, -1.0f, -1.0f}, {0.0f, 1.0f}}, {{ 1.0f, 1.0f, -1.0f}, {1.0f, 0.0f}}, {{ 1.0f, -1.0f, -1.0f}, {1.0f, 1.0f}}, }; glGenVertexArraysOES(1, &_vertexArray); glBindVertexArrayOES(_vertexArray); glGenBuffers(1, &_vertexBuffer); glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_STATIC_DRAW); glEnableVertexAttribArray(GLKVertexAttribPosition); glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid *)offsetof(Vertex, position)); glEnableVertexAttribArray(GLKVertexAttribTexCoord0); glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid *)offsetof(Vertex, texcoord)); glBindVertexArrayOES(0); 相结合 - 其glBindVertexArrayOES(_vertexArray); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 属性是默认的标识转换,其GLKBaseEffect属性设置为您通过加载的纹理的transform texture2d0或其他方式 - 您将获得一个带有纹理的视图填充广告牌。


    最后,YUV部分...我将大部分时间。你在哪里获得YUV纹理数据?如果它来自设备相机,您应该查看name / GLKTextureLoaderthis answer涵盖。无论如何,您应该能够使用CVOpenGLESTexture扩展来处理YUV纹理,如this answer所述。您还可以查看this answer有关编写片段着色器的帮助,以便在运行中将YUV处理为RGB。