简介

OpenGL ES的FrameBuffer是渲染发生的地方,普通的2D图形的渲染默认发生在屏幕上;而三维的图形渲染则除了包括像素点的颜色,还有Depth Buffer,Stencil Buffer等其他空间。因此,FrameBuffer就是一个这些Buffer的一个集合。

默认情况下,FrameBuffer存在于现存中,但是当需要进行多次渲染或者离屏渲染的时候,可以通过创建一个离屏的FrameBuffer进行渲染。当需要渲染3D效果时,除了创建frameBuffer以外,还需要创建相应的Render Buffer, Depth Buffer, Stencil Buffer,并且将它们attach到frameBuffer上;而当只需要渲染2D图形时,可以直接生成一个Texture,并且将FrameBuffer渲染的结果放入Texture中。

生成一个FrameBuffer的代码:

glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);

由于存在离屏渲染的情况,实际渲染开始之前,需要先激活目标FrameBuffer,而在渲染完成之后,需要将FrameBuffer绑定为0,回到默认的FrameBuffer,才能够显示在屏幕上:

glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
//Rendering Code
glBindFramebuffer(GL_FRAMEBUFFER, 0);

如果要渲染一个2D图像到一个Texture上,则还需要先生成一个Texture,并且将Texture绑定到FrameBuffer上。当使用FrameBuffer进行流的传递的时候,则可以使用这个Texture:

glActiveTexture(GL_TEXTURE1);
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);
// This is necessary for non-power-of-two textures
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glBindTexture(GL_TEXTURE_2D, _texture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (int)_size.width, (int)_size.height, 0,GL_RGBA, GL_UNSIGNED_BYTE, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _texture, 0);

GPUImageFrameBuffer

GPUImageFrameBuffer不只是简单的对OpenGL ES的FrameBuffer的对象化封装,而是一个对渲染对象的对象化封装。它生成的可以是一个带有Texture作为Attachment的FrameBuffer,也可以仅仅生成一个Texture作为渲染对象。它的主要功能有:

  • 生成渲染对象,FrameBuffer或者Texture,带的参数包括size和texture option,这两个参数主要是用于FrameBuffer的重用,GPUImageFramebufferCache中会介绍到:
- (id)initWithSize:(CGSize)framebufferSize;
- (id)initWithSize:(CGSize)framebufferSize textureOptions:(GPUTextureOptions)fboTextureOptions onlyTexture:(BOOL)onlyGenerateTexture;
- (id)initWithSize:(CGSize)framebufferSize overriddenTexture:(GLuint)inputTexture;
  • FrameBuffer的管理,在渲染的时候激活frameBuffer:
- (void)activateFramebuffer;
  • FrameBuffer的引用计数。同样用于FrameBuffer的重用,GPUImageFramebufferCache会详细介绍:
- (void)lock;
- (void)unlock;
- (void)clearAllLocks;
- (void)disableReferenceCounting;
- (void)enableReferenceCounting;
  • 从FrameBuffer中生成图片或者源数据:
- (CGImageRef)newCGImageFromFramebufferContents;
- (GLubyte *)byteBuffer;

GPUImageFrameBuffer的引用计数

由于GPUImageFrameBuffer需要重用,因此,当FrameBuffer的引用为0的时候,这个FrameBuffer就会被放到Cache中,来给其他的需要的地方进行使用。因此作者给GPUImageFrameBuffer引入了引用计数的概念。

引用计数的概念其实和OC自带的MRC有点类似,每当一个地方需要使用这个FrameBuffer的时候,手动调用lock方法,使引用计数+1;当渲染完毕或者这个FrameBuffer使用完毕的时候,手动调用unlock方法,使引用计数-1;当引用计数为0的时候,FrameBuffer会被归还到Cache中。

调用增加FrameBuffer引用计数方法的地方:

  1. 每次从Cache中获取到一个FrameBuffer的时候,都会调用一次lock方法,因为既然获取了FrameBuffer就是需要使用它进行渲染的时候,因此这个是最合适的调用时机;
  2. 将一个FrameBuffer作为Output传给下一个Input的时候,会调用setInputFrameBuffer:atIndex:方法。因为这个FrameBuffer会被传递给下一个input进行使用,因此我们需要手动的将这个FrameBuffer的引用计数+1;
  3. 如果需要将一个Filter的输出进行截图的话(usingNextFrameForImageCapture == YES),也需要手动调用lock方法。因为默认情况下,当下一个input渲染完成之后,就会释放这个FrameBuffer。如果你需要对当前的Filter的输出进行截图的话,则需要保留住这个FrameBuffer。

调用减少FrameBuffer引用计数方法的地方:

  1. 在renderToTextureWithVertices:textureCoordinates:渲染完成之后,需要将从上一个Output中传过来的所有InputFrameBuffer都unlock掉;
  2. 在informTargetsAboutNewFrameAtTime:通知下一个input之后,需要将当前的这个Output中的outputFrameBuffer给unlock掉;

不需要引用计数的情况:

在有些地方我们是不需要使用引用计数的,比如GPUImagePicture。因为生成了Picture之后,它只会有一个outputFrameBuffer。而且这个frameBuffer只有在GPUImagePicture初始化的时候生成。因此这个FrameBuffer不能被释放,否则以后它的target就不能使用了。因此GPUImagePicture初始化的时候调用了disableReferenceCounting方法。只有当这个GPUImagePicture在dealloc的时候才能被释放。

GPUImage源码解读之GPUImageFramebuffer的更多相关文章

  1. GPUImage源码解读之GPUImageFramebufferCache

    简介 由于GPUImage添加滤镜可以形成一个FilterChain,因此,在渲染的过程中,可能会需要很多个FrameBuffer,但是正如上文所说,每生成一个FrameBuffer都需要占用一定的内 ...

  2. GPUImage源码解读之GLProgram

    简述 GLProgram是GPUImage中代表openGL ES 中的program,具有glprogram功能.其实是作者对OpenGL ES program的面向对象封装 初始化 - (id)i ...

  3. GPUImage源码解读之GPUImageContext

    GPUImageContext类,提供OpenGL ES基本上下文,GPUImage相关处理线程,GLProgram缓存.帧缓存.由于是上下文对象,因此该模块提供的更多是存取.设置相关的方法. 属性列 ...

  4. SDWebImage源码解读之SDWebImageDownloaderOperation

    第七篇 前言 本篇文章主要讲解下载操作的相关知识,SDWebImageDownloaderOperation的主要任务是把一张图片从服务器下载到内存中.下载数据并不难,如何对下载这一系列的任务进行设计 ...

  5. SDWebImage源码解读 之 NSData+ImageContentType

    第一篇 前言 从今天开始,我将开启一段源码解读的旅途了.在这里先暂时不透露具体解读的源码到底是哪些?因为也可能随着解读的进行会更改计划.但能够肯定的是,这一系列之中肯定会有Swift版本的代码. 说说 ...

  6. SDWebImage源码解读 之 UIImage+GIF

    第二篇 前言 本篇是和GIF相关的一个UIImage的分类.主要提供了三个方法: + (UIImage *)sd_animatedGIFNamed:(NSString *)name ----- 根据名 ...

  7. SDWebImage源码解读 之 SDWebImageCompat

    第三篇 前言 本篇主要解读SDWebImage的配置文件.正如compat的定义,该配置文件主要是兼容Apple的其他设备.也许我们真实的开发平台只有一个,但考虑各个平台的兼容性,对于框架有着很重要的 ...

  8. SDWebImage源码解读_之SDWebImageDecoder

    第四篇 前言 首先,我们要弄明白一个问题? 为什么要对UIImage进行解码呢?难道不能直接使用吗? 其实不解码也是可以使用的,假如说我们通过imageNamed:来加载image,系统默认会在主线程 ...

  9. SDWebImage源码解读之SDWebImageCache(上)

    第五篇 前言 本篇主要讲解图片缓存类的知识,虽然只涉及了图片方面的缓存的设计,但思想同样适用于别的方面的设计.在架构上来说,缓存算是存储设计的一部分.我们把各种不同的存储内容按照功能进行切割后,图片缓 ...

随机推荐

  1. Web前端面试指导(十五):CSS样式-display有哪些作用?

    题目点评 其实就是要你说清楚该属性有哪些值,每个值都有什么作用,这个题目可以答得很简单,但要答全也并非是一件容易的事情. 元素默认的display值的情况如下(这个一般很少人注意这一点) block( ...

  2. 子div设置float后会导致父div无法自动撑开

    本文是从简书复制的, markdown语法可能有些出入, 想看"正版"和更多内容请关注 简书: 小贤笔记 注: 文章部分转载 彩泉 - 博客园 原因:内部的DIV因为float:l ...

  3. Android ListView复制、删除的实现

    适配器MyAdapter: package com.zihao.adapter; import java.util.List; import com.zihao.popdemo.R; import c ...

  4. 【Android】修改包名

    工程写的差不多了才发现原来用的包名还是自己尝试性的进行写代码的时候用到的.但apk的发布,google map api的申请等等方面都需要用到一个比较规范的包名.这就涉及到修改包名的问题. 包名一开始 ...

  5. 使用C3的一些新属性绘制谷歌浏览器的图标

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

  6. leetcode-Maximum Product Subarray-ZZ

    http://blog.csdn.net/v_july_v/article/details/8701148 假设数组为a[],直接利用动归来求解,考虑到可能存在负数的情况,我们用Max来表示以a结尾的 ...

  7. python接口自动化4-绕过验证码登录(cookie) (转载)

    前言 有些登录的接口会有验证码:短信验证码,图形验证码等,这种登录的话验证码参数可以从后台获取的(或者查数据库最直接). 获取不到也没关系,可以通过添加cookie的方式绕过验证码. 一.抓登录coo ...

  8. 404错误 标签: servlet浏览器 2016-11-16 16:58 61人阅读 评论(0) 收藏

    404是资源没有找到,一般由于以下几个方面导致: 1.路径出错: a)检查web.xml中servlet的配置是否出错 b)浏览器访问是路径书写方式:http://localhost:8080/项目名 ...

  9. UML用例图间关系说明

    用例间一般存在如下四种关系: 1."通信"关系(<<cmmunicate>>构造型): "通信"关系:使用实心的关联线或带<< ...

  10. 关于Struts2中的ognl-2.6.11.jar和ognl-2.7.3.jar解决思路

    关于Struts2中的ognl-2.6.11.jar和ognl-2.7.3.jar建了一个简单的工程:导入的jar包有六个,包括commons-fileupload-1.2.1.jarcommons- ...