首页 文章 精选 留言 我的

精选列表

搜索[直播],共5188篇文章
优秀的个人博客,低调大师

开发一个完整iOS直播app——GPUImage渲染底层实现-opengl

一、前言 本篇主要讲解GPUImage底层是如何渲染的,GPUImage底层使用的是OPENGL,操控GPU来实现屏幕展示 由于网上OpenGL实战资料特别少,官方文档对一些方法也是解释不清楚,避免广大同学再次爬坑,本篇讲解了不少OpenGL的知识,并且还讲解了花了大量时间解决bug的注意点,曾经因为对glDrawArrays这个方法不熟悉,遇上Bug,晚上熬到凌晨四点都没解决,还是第二天中午解决的。 如果喜欢我的文章,可以关注我微博:袁峥Seemygo,也可以来小码哥,了解下我们的iOS培训课程。后续还会更新更多内容,有任何问题,欢迎关注微,信号“小码哥订阅号”。 二、GPUImageVideoCamera 可以捕获采集的视频数据 关键是捕获到一帧一帧视频数据如何展示? 通过这个方法可以获取采集的视频数据 采集视频注意点:要设置采集竖屏,否则获取的数据是横屏 通过AVCaptureConnection就可以设置 三、自定义OpenGLView渲染视频 暴露一个接口,获取采集到的帧数据,然后把帧数据传递给渲染View,展示出来 四、利用OpenGL渲染帧数据并显示 导入头文件#import <GLKit/GLKit.h>,GLKit.h底层使用了OpenGLES,导入它,相当于自动导入了OpenGLES 步骤 01-自定义图层类型 02-初始化CAEAGLLayer图层属性 03-创建EAGLContext 04-创建渲染缓冲区 05-创建帧缓冲区 06-创建着色器 07-创建着色器程序 08-创建纹理对象 09-YUV转RGB绘制纹理 10-渲染缓冲区到屏幕 11-清理内存 01-自定义图层类型 为什么要自定义图层类型CAEAGLLayer? CAEAGLLayer是OpenGL专门用来渲染的图层,使用OpenGL必须使用这个图层 02-初始化CAEAGLLayer图层属性 1.不透明度(opaque)=YES,CALayer默认是透明的,透明性能不好,最好设置为不透明. 2.设置绘图属性 kEAGLDrawablePropertyRetainedBacking :NO (告诉CoreAnimation不要试图保留任何以前绘制的图像留作以后重用) kEAGLDrawablePropertyColorFormat :kEAGLColorFormatRGBA8 (告诉CoreAnimation用8位来保存RGBA的值) 其实设置不设置都无所谓,默认也是这个值,只不过GPUImage设置了 03-创建EAGLContext 需要将它设置为当前context,所有的OpenGL ES渲染默认渲染到当前上下文 EAGLContext管理所有使用OpenGL ES进行描绘的状态,命令以及资源信息,要绘制东西,必须要有上下文,跟图形上下文类似。 当你创建一个EAGLContext,你要声明你要用哪个version的API。这里,我们选择OpenGL ES 2.0 04-创建渲染缓冲区 有了上下文,openGL还需要在一块buffer进行描绘,这块buffer就是RenderBuffer OpenGLES 总共有三大不同用途的color buffer,depth buffer 和 stencil buffer. 最基本的是color buffer,创建它就好了 函数glGenRenderbuffers 它是为renderbuffer(渲染缓存)申请一个id(名字),创建渲染缓存 参数n表示申请生成renderbuffer的个数 参数renderbuffers返回分配给renderbuffer(渲染缓存)的id 。 注意:返回的id不会为0,id 0 是OpenGL ES保留的,我们也不能使用id 为0的renderbuffer(渲染缓存)。 函数glBindRenderbuffer 告诉OpenGL:我在后面引用GL_RENDERBUFFER的地方,其实是引用_colorRenderBuffer 参数target必须为GL_RENDERBUFFER 参数renderbuffer就是使用glGenRenderbuffers生成的id 。 当指定id的renderbuffer第一次被设置为当前renderbuffer时,会初始化该 renderbuffer对象,其初始值为: 函数renderbufferStorage 把渲染缓存(renderbuffer)绑定到渲染图层(CAEAGLLayer)上,并为它分配一个共享内存。 参数target,为哪个renderbuffer分配存储空间 参数drawable,绑定在哪个渲染图层,会根据渲染图层里的绘图属性生成共享内存。 实战代码 05-创建帧缓冲区 它相当于buffer(color, depth, stencil)的管理者,三大buffer可以附加到一个framebuffer上 本质是把framebuffer内容渲染到屏幕 函数glFramebufferRenderbuffer 该函数是将相关buffer()三大buffer之一)attach到framebuffer上,就会自动把渲染缓存的内容填充到帧缓存,在由帧缓存渲染到屏幕 参数target,哪个帧缓存 参数attachment是指定renderbuffer被装配到那个装配点上,其值是GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT中的一个,分别对应 color,depth和 stencil三大buffer。 renderbuffertarget:哪个渲染缓存 renderbuffer渲染缓存id 06-创建着色器 着色器 什么是着色器? 通常用来处理纹理对象,并且把处理好的纹理对象渲染到帧缓存上,从而显示到屏幕上。 提取纹理信息,可以处理顶点坐标空间转换,纹理色彩度调整(滤镜效果)等操作。 着色器分为顶点着色器,片段着色器 顶点着色器用来确定图形形状 片段着色器用来确定图形渲染颜色 步骤: 1.编辑着色器代码 2.创建着色器 3.编译着色器 只要创建一次,可以在一开始的时候创建 着色器代码 实战代码 07-创建着色器程序 步骤: 1.创建程序 2.贴上顶点和片段着色器 3.绑定attribute属性 4.连接程序 5.绑定uniform属性 6.运行程序 注意点:第3步和第5步,绑定属性,必须有顺序,否则绑定不成功,造成黑屏 08-创建纹理对象 纹理 采集的是一张一张的图片,可以把图片转换为OpenGL中的纹理, 然后再把纹理画到OpenGL的上下文中 什么是纹理?一个纹理其实就是一幅图像。 纹理映射,我们可以把这幅图像的整体或部分贴到我们先前用顶点勾画出的物体上去. 比如绘制一面砖墙,就可以用一幅真实的砖墙图像或照片作为纹理贴到一个矩形上,这样,一面逼真的砖墙就画好了。如果不用纹理映射的方法,则墙上的每一块砖都必须作为一个独立的多边形来画。另外,纹理映射能够保证在变换多边形时,多边形上的纹理图案也随之变化。 纹理映射是一个相当复杂的过程,基本步骤如下: 1)激活纹理单元、2)创建纹理 、3)绑定纹理 、4)设置滤波 注意:纹理映射只能在RGBA方式下执行 函数glTexParameter 控制滤波,滤波就是去除没用的信息,保留有用的信息 一般来说,纹理图像为正方形或长方形。但当它映射到一个多边形或曲面上并变换到屏幕坐标时,纹理的单个纹素很少对应于屏幕图像上的像素。根据所用变换和所用纹理映射,屏幕上单个象素可以对应于一个纹素的一小部分(即放大)或一大批纹素(即缩小) 固定写法 函数glPixelStorei 设置像素存储方式 pname:像素存储方式名 一种是GL_PACK_ALIGNMENT用于将像素数据打包,一般用于压缩。 另一种是GL_UNPACK_ALIGNMENT,用于将像素数据解包,一般生成纹理对象,就需要用到解包. param:用于指定存储器中每个像素行有多少个字节对齐。这个数值一般是1、2、4或8, 一般填1,一个像素对应一个字节; 函数CVOpenGLESTextureCacheCreateTextureFromImage 根据图片生成纹理 参数allocator kCFAllocatorDefault,默认分配内存 参数textureCache 纹理缓存 参数sourceImage 图片 参数textureAttributes NULL 参数target , GL_TEXTURE_2D(创建2维纹理对象) 参数internalFormat GL_LUMINANCE,亮度格式 参数width 图片宽 参数height 图片高 参数format GL_LUMINANCE 亮度格式 参数type 图片类型 GL_UNSIGNED_BYTE 参数planeIndex 0,切面角标,表示第0个切面 参数textureOut 输出的纹理对象 实战代码 09-YUV转RGB绘制纹理 纹理映射只能在RGBA方式下执行 而采集的是YUV,所以需要把YUV 转换 为 RGBA, 本质其实就是改下矩阵结构 注意点(熬夜凌晨的bug):glDrawArrays如果要绘制着色器上的点和片段,必须和着色器赋值代码放在一个代码块中,否则找不到绘制的信息,就绘制不上去,造成屏幕黑屏 之前是把glDrawArrays和YUV转RGB方法分开,就一直黑屏. 函数glUniform1i 指定着色器中亮度纹理对应哪一层纹理单元 参数location:着色器中纹理坐标 参数x:指定那一层纹理 函数glEnableVertexAttribArray 开启顶点属性数组,只有开启顶点属性,才能给顶点属性信息赋值 函数glVertexAttribPointer 设置顶点着色器属性,描述属性的基本信息 参数indx:属性ID,给哪个属性描述信息 参数size:顶点属性由几个值组成,这个值必须位1,2,3或4; 参数type:表示属性的数据类型 参数normalized:GL_FALSE表示不要将数据类型标准化 参数stride 表示数组中每个元素的长度; 参数ptr 表示数组的首地址 函数glBindAttribLocation 给属性绑定ID,通过ID获取属性,方便以后使用 参数program 程序 参数index 属性ID 参数name 属性名称 函数glDrawArrays 作用:使用当前激活的顶点着色器的顶点数据和片段着色器数据来绘制基本图形 mode:绘制方式 一般使用GL_TRIANGLE_STRIP,三角形绘制法 first:从数组中哪个顶点开始绘制,一般为0 count:数组中顶点数量,在定义顶点着色器的时候,就定义过了,比如vec4,表示4个顶点 注意点,如果要绘制着色器上的点和片段,必须和着色器赋值代码放在一个代码块中,否则找不到绘制的信息,就绘制不上去,造成屏幕黑屏。 实战代码 请点击此处输入图片描述请点击此处输入图片描述 10-渲染缓冲区到屏幕 注意点:必须设置窗口尺寸glViewport 注意点:渲染代码必须调用[EAGLContext setCurrentContext:_context] 原因:因为是多线程,每一个线程都有一个上下文,只要在一个上下文绘制就好,设置线程的上下文为我们自己的上下文,就能绘制在一起了,否则会黑屏. 注意点:每次创建纹理前,先把之前的纹理引用清空[self cleanUpTextures],否则卡顿 函数glViewport 设置OpenGL渲染窗口的尺寸大小,一般跟图层尺寸一样. 注意:在我们绘制之前还有一件重要的事情要做,我们必须告诉OpenGL渲染窗口的尺寸大小 方法presentRenderbuffer 是将指定renderbuffer呈现在屏幕上 实战代码 11-清理内存 注意:只要有Ref结尾的,都需要自己手动管理,清空 函数glClearColor 设置一个RGB颜色和透明度,接下来会用这个颜色涂满全屏. 函数glClear 用来指定要用清屏颜色来清除由mask指定的buffer,mask可以是 GL_COLOR_BUFFER_BIT,GL_DEPTH_BUFFER_BIT和GL_STENCIL_BUFFER_BIT的自由组合。 在这里我们只使用到 color buffer,所以清除的就是 clolor buffer。 GPUImage工作原理 GPUImage最关键在于GPUImageFramebuffer这个类,这个类会保存当前处理好的图片信息。 GPUImage是通过一个链条处理图片,每个链条通过target连接,每个target处理完图片后,会生成一个GPUImageFramebuffer对象,并且把图片信息保存到GPUImageFramebuffer。 这样比如targetA处理好,要处理targetB,就会先取出targetA的图片,然后targetB在targetA的图片基础上在进行处理. 本文转自ljianbing51CTO博客,原文链接:http://blog.51cto.com/ljianbing/1921654 ,如需转载请自行联系原作者

优秀的个人博客,低调大师

【8月9日直播回顾】研发协同RDC敏捷项目管理实践

扫描上述二维码或点我直达 免费领! 一份对敏捷项目管理的研究显示,在收益、质量、及周期三方面都分别得到了10%到20%的改善,而在成本方面则减少了54%。 敏捷到底是什么?和传统的协作方式有什么区别?敏捷项目协作和研发如何实行?本期我们邀请到了阿里云研发协同RDC项目域的产品专家方奕东老师给我们答疑解惑。 方奕东(光脉),阿里巴巴产品专家,阿里云研发协同RDC项目域的产品经理,负责阿里云研发协同RDC的项目和项目集、需求、任务、缺陷和迭代管理等产品功能设计工作,也是阿里百年技术课堂最受欢迎的项目管理域的讲师。方奕东(光脉)参加PMI杭州分享现场2015年加入阿里巴巴,在加入阿里巴巴之前,担任过大型项目和项目组合管理软件的架构师,有多年项目管理经验,是一名认证的PMP和ScrumMaster。 2017年8月9日20:00,方奕东老师将以阿

资源下载

更多资源
优质分享App

优质分享App

近一个月的开发和优化,本站点的第一个app全新上线。该app采用极致压缩,本体才4.36MB。系统里面做了大量数据访问、缓存优化。方便用户在手机上查看文章。后续会推出HarmonyOS的适配版本。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

用户登录
用户注册