在iOS上使用OpenGL ES渲染YUV

33 篇文章 0 订阅

转自:http://blog.csdn.net/cpluser/article/details/41720431


1)创建OpenGL context
[[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];


2)layer设置成不透明
_eaglLayer = (CAEAGLLayer*) self.layer;
_eaglLayer.opaque = YES;


3)创建YUV texture
glGenTextures(1, &m_nTexturePlanarY);
glGenTextures(1, &m_nTexturePlanarU);
glGenTextures(1, &m_nTexturePlanarV);


4)添加shader
GLuint vertexShader = CompileShader(_VERTEX_SHADER_Y_U_V, GL_VERTEX_SHADER);
GLuint fragmentShader = CompileShader(_FRAGMENT_SHADER_Y_U_V, GL_FRAGMENT_SHADER);
glAttachShader(m_nProgramHandle, vertexShader);
glAttachShader(m_nProgramHandle, fragmentShader);


摘录一段GLSL介绍
OpenGL着色语言(GLSL―OpenGL Shading Language)是用来在OpenGL中着色编程的语言,也即开发人员写的短小的自定义程序,他们是在图形卡的GPU (Graphic Processor Unit图形处理单元)上执行的,代替了固定的渲染管线的一部分,使渲染管线中不同层次具有可编程型。比如:视图转换、投影转换等。GLSL(GL Shading Language)的着色器代码分成2个部分:Vertex Shader(顶点着色器)和Fragment(片断着色器),有时还会有Geometry Shader(几何着色器)。负责运行顶点着色的是顶点着色器。它可以得到当前OpenGL 中的状态,GLSL内置变量进行传递。GLSL其使用C语言作为基础高阶着色语言,避免了使用汇编语言或硬件规格语言的复杂性。


5)创建render buffer
glGenRenderbuffers(1, &nColorRenderBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, nColorRenderBuffer);


6)创建frame buffer
glGenFramebuffers(1, &nFrameBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, nFrameBuffer);


7)创建viewport
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &nBackingWidth);
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &nBackingHeight);
glViewport(0, 0, nBackingWidth, nBackingHeight);   
glClearColor(0.0, 0.0, 0.0, 1.0);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);


8)设置四个顶点,四个顶点的设置顺序不同,可以实现图像的上下、左右翻转。

在最后render到屏幕时会用到这些顶点,如下

glVertexAttribPointer(m_nPositionSlot, 2, GL_FLOAT, 0, 0, m_fSquareVertices);
glVertexAttribPointer(m_nTexCoordSlot, 2, GL_FLOAT, 0, 0, m_fTextureVertices);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);


9)YUV数据到来时,即可以开始渲染,步骤如下


a. YUV数据更新到texture上
GLTexImage2D(m_nTexturePlanarY, m_pFrameData, m_nTextureWidth, m_nTextureHeight);
GLTexImage2D(m_nTexturePlanarU, pBuffer - (nWidthUV * nHeightUV), nWidthUV, nHeightUV);
GLTexImage2D(m_nTexturePlanarV, pBuffer, nWidthUV, nHeightUV);


b. Bind YUV texture
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_nTexturePlanarY);
glUniform1i(m_nTextureUniformY, 0);
   
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, m_nTexturePlanarU);
glUniform1i(m_nTextureUniformU, 1);
   
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, m_nTexturePlanarV);
glUniform1i(m_nTextureUniformV, 2);


c. 绘制图像
glVertexAttribPointer(m_nPositionSlot, 2, GL_FLOAT, 0, 0, m_fSquareVertices);
glVertexAttribPointer(m_nTexCoordSlot, 2, GL_FLOAT, 0, 0, m_fTextureVertices);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);


d. 在屏幕上显示出来
[m_pContext presentRenderbuffer:GL_RENDERBUFFER];


10)程序退出时释放所有之前分配出来的资源
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。
### 回答1: 如果要在 C 语言中使用 OpenGL 渲染 YUV 并且能够等比例拉伸,需要先将 YUV 数据转换为 RGB 格式,再在 OpenGL 中进行渲染。在渲染之前,需要配置投影矩阵和视图矩阵,以实现等比例拉伸效果。在绘制矩形时,需要注意纹理坐标的映射关系,以保证正确地显示图像。 以下是一份简化的代码示例: ``` #include <GL/gl.h> #include <GL/glu.h> void draw_yuv(int width, int height, const unsigned char *yuv) { // 将 YUV 数据转换为 RGB 数据 // ... // 启用 2D 纹理 glEnable(GL_TEXTURE_2D); // 创建纹理对象 GLuint texture; glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); // 设置纹理参数 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // 上传纹理数据 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, rgb); // 设置投影矩阵和视图矩阵,实现等比例拉伸 // ... // 开始绘制 glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex2f(-1.0f, -1.0f); glTexCoord2f(1.0f, 0.0f); glVertex2f(1.0f, -1.0f); glTexCoord2f(1.0f, 1.0f); glVertex2f(1.0f, 1.0 ### 回答2: 使用C语言结合OpenGL渲染YUV图像并实现等比例拉伸的主要步骤如下: 1. 导入OpenGL的库文件和头文件,并创建一个OpenGL的窗口。 2. 读取YUV图像的数据,并将其存储到内存中。 3. 创建一个纹理对象,并将YUV图像数据通过纹理映射到OpenGL中。 4. 设置OpenGL的纹理参数,包括采样方式和拉伸方式。 5. 在OpenGL的绘制回调函数中,绑定纹理对象并绘制一个矩形。 6. 在绘制矩形之前,根据窗口的宽高和YUV图像的宽高比例,计算出矩形的坐标和尺寸,从而实现等比例拉伸。 7. 在绘制结束后,交换绘制缓冲区的数据并更新窗口的显示。 具体实现代码如下: ```c #include <stdio.h> #include <stdlib.h> #include <GL/glut.h> unsigned char* yuvData; // 存储YUV图像数据 GLuint textureID; // 纹理ID int windowWidth = 640; // 窗口宽度 int windowHeight = 480; // 窗口高度 int yuvWidth = 352; // YUV图像宽度 int yuvHeight = 288; // YUV图像高度 void display() { glClear(GL_COLOR_BUFFER_BIT); glBindTexture(GL_TEXTURE_2D, textureID); glBegin(GL_QUADS); glTexCoord2f(0.0, 0.0); glVertex2f(-1.0, -1.0); glTexCoord2f(1.0, 0.0); glVertex2f(1.0, -1.0); glTexCoord2f(1.0, 1.0); glVertex2f(1.0, 1.0); glTexCoord2f(0.0, 1.0); glVertex2f(-1.0, 1.0); glEnd(); glBindTexture(GL_TEXTURE_2D, 0); glutSwapBuffers(); } void reshape(int width, int height) { glViewport(0, 0, width, height); // 计算等比例拉伸后的矩形尺寸 float aspectRatio = (float)yuvWidth / (float)yuvHeight; float windowRatio = (float)width / (float)height; int newWidth, newHeight; if (windowRatio > aspectRatio) { newWidth = height * aspectRatio; newHeight = height; } else { newWidth = width; newHeight = width / aspectRatio; } // 计算等比例拉伸后的矩形位置 int posX = (width - newWidth) / 2; int posY = (height - newHeight) / 2; glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-1, 1, -1, 1, -1, 1); glMatrixMode(GL_MODELVIEW); glViewport(posX, posY, newWidth, newHeight); } int main(int argc, char **argv) { // 读取YUV图像数据 FILE *yuvFile = fopen("input.yuv", "rb"); yuvData = (unsigned char*)malloc(yuvWidth * yuvHeight * 3 / 2); fread(yuvData, 1, yuvWidth * yuvHeight * 3 / 2, yuvFile); fclose(yuvFile); // 初始化OpenGL glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA); glutInitWindowSize(windowWidth, windowHeight); glutCreateWindow("YUV rendering with OpenGL"); // 创建纹理对象并绑定YUV图像数据 glGenTextures(1, &textureID); glBindTexture(GL_TEXTURE_2D, textureID); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, yuvWidth, yuvHeight, 0, GL_YUV420_EXT, GL_UNSIGNED_BYTE, yuvData); // 设置纹理参数 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // 注册绘制和窗口调整回调函数 glutDisplayFunc(display); glutReshapeFunc(reshape); // 进入主循环 glutMainLoop(); // 释放内存 free(yuvData); return 0; } ``` 以上代码使用OpenGL绘制一个矩形,并将YUV图像通过纹理映射到矩形上,实现了等比例拉伸。在reshape回调函数中,根据窗口的宽高和YUV图像的宽高比例,计算出了矩形的位置和尺寸,从而实现了等比例拉伸效果。 ### 回答3: 使用C语言结合OpenGL库可以实现YUV渲染并且能够等比例拉伸的功能。 首先,我们需要读取YUV数据文件,并将其解析为Y、U、V三个分量。 然后,创建OpenGL窗口并设置好OpenGL环境。 接下来,在窗口创建之后,我们需要创建OpenGL纹理对象,并将YUV数据绑定到纹理上。这可以通过使用glTexImage2D函数实现,其中的格式参数应设置为GL_LUMINANCE、GL_LUMINANCE_ALPHA或GL_RGB,具体取决于输入的YUV数据类型。同时,需要注意设置纹理的宽度和高度,即拉伸的比例。 接下来,我们需要在OpenGL窗口中绘制纹理。我们可以使用glBegin和glEnd函数配合glTexCoord和glVertex等函数,将纹理映射到窗口上进行绘制。同时,为了实现等比例拉伸,需要在绘制之前设置glMatrixMode函数为GL_PROJECTION,并使用glOrtho函数设置视口的宽度和高度。 最后,通过调用glutMainLoop函数进入主循环中,以便持续渲染窗口。 综上所述,通过使用C语言和OpenGL库,我们可以实现以YUV格式渲染图像,并且能够进行等比例拉伸的功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值