1

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

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

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

有一个类GLKBaseEffect将具有基本着色器。我不知道要设置哪些属性,所以我只是创建它并prepareToDraw在每次渲染之前调用。

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

// 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(我到目前为止还没有探索过)?

4

1 回答 1

4

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

  • 如何用GLKViewvs画画CAEAGLLayer
  • 一般如何GLKBaseEffectGLKTextureLoader适合 OpenGL ES 绘图
  • 拥有纹理后如何绘制纹理
  • 如何渲染 YUV 图像数据

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


GLKView对于您想要做的任何 OpenGL ES 绘图来说都很好——它为您完成了您链接到的旧文档所做的一切(设置帧缓冲区、CAEAGLLayers 等),因此您不必编写该代码。在GLKView绘图方法(drawRect:glkView:drawInRect:,取决于您是在子类还是委托中绘图)内部,您编写与CAEAGLLayer(或任何其他系统)相同的 OpenGL ES 绘图代码。


您可以相互独立地使用GLKViewGLKTextureLoader和。GLKBaseEffect如果您想编写所有自己的绘图代码并使用自己的着色器,您可以在GLKView不使用GLKBaseEffect. (你甚至可以混合和匹配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设置的- 您将获得一个带有纹理的视图填充广告牌.nameGLKTextureLoader


最后,YUV 部分......我将主要针对它。你从哪里得到你的 YUV 纹理数据?如果它来自设备摄像头,您应该查看CVOpenGLESTexture/ CVOpenGLESTextureCache,正如这个答案所涵盖的那样。无论如何,您应该能够使用APPLE_rgb_422扩展处理 YUV 纹理,如本答案所述。您还可以查看此答案以获取一些帮助编写片段着色器以动态处理 YUV 到 RGB。

于 2013-09-18T22:32:50.433 回答