繁体   English   中英

使用GLKit openGL - iOS绘制YUV图像

[英]Draw YUV image using GLKit openGL - iOS

我想在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进行渲染的教程( EAGLLayer我还没有探讨过)?

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

  • 如何使用GLKViewCAEAGLLayer绘制
  • GLKBaseEffectGLKTextureLoader如何适用于OpenGL ES绘图
  • 一旦有了纹理,如何绘制纹理
  • 如何渲染YUV图像数据

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


GLKView适用于您想要做的任何OpenGL ES绘图 - 它可以完成您链接的旧文档所做的一切(为您设置framebuffers, CAEAGLLayer等),因此您不必编写该代码。 GLKView绘图方法( drawRect:glkView:drawInRect:取决于您是否在子类或委托中绘图)中,您编写了与CAEAGLLayer (或任何其他系统)相同的OpenGL ES绘图代码。


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


一旦获得纹理,无论是通过GLKTextureLoader还是自己读取/解码数据并将其提供给glTexImage2D ,使用它绘制有三个基本步骤:

  1. 使用glBindTexture绑定纹理名称。
  2. 绘制一些要纹理化的几何体(使用glDrawArraysglDrawElements或类似物)
  3. 有一个片段着色器,可以查找纹素并输出颜色。

如果您只想绘制填充视图的图像,只需绘制四边形(两个三角形)。 这是我想用于绘制全屏时使用一个四边形设置顶点数组对象的代码:

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属性设置为您通过GLKTextureLoader或其他方式加载的纹理的name - 您将获得一个视图填充广告牌你的纹理就可以了。


最后,YUV部分......我将大部分时间。 你在哪里获得YUV纹理数据? 如果它来自设备相机,您应该查看CVOpenGLESTexture / CVOpenGLESTextureCache ,如本答案所述 无论如何,您应该能够使用APPLE_rgb_422扩展来处理YUV纹理,如本答案所述 您还可以查看此答案,以获得一些帮助编写片段着色器以便在运行时将YUV处理为RGB。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM