简介

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. JavaScript常用类

    JS常用类 一.Number 1.常用数字 整数:10 小数:3.14 科学计数法:1e5 | 1e-5 正负无穷:Infinity | -Infinity 2.常用进制 二进制:0b1010 八进制 ...

  2. 原生js操作DOM基础-笔记

    原文参考http://mp.weixin.qq.com/s?__biz=MzU3MDA0NTMzMA==&mid=2247485490&idx=1&sn=15197b4b53e ...

  3. Linux基础之命令练习Day1-init,who,date,cal,man,clear,passwd,su,whoami,mkdir,touch,rm,cp,mv,head,tail,more,less,echo

    开启Linux操作系统,要求以root用户登录GNOME图形界面,语言支持选择为汉语 使用快捷键切换到虚拟终端2,使用普通用户身份登录,查看系统提示符 使用命令退出虚拟终端2上登录的用户 使用快捷键切 ...

  4. [转]ggplot2用法简单介绍

    简介 ggplot2包是基于Wilkinson在<Grammar of Graphics>一书中所提出的图形语法的具体实现, 这套图形语法把绘图过程归纳为data, transformat ...

  5. 记录code修改

    package com.hesheng.myapplication; import android.content.Context;import android.graphics.Bitmap;imp ...

  6. 使用pdb调试python脚本

    pdb 是 python 自带的一个包,为 python 程序提供了一种交互的源代码调试功能,主要特性包括设置断点.单步调试.进入函数调试.查看当前代码.查看栈片段.动态改变变量的值等.pdb 提供了 ...

  7. 微软牛津计划——声纹识别与视频识别API上线啦!

    上个月,我们发布了牛津计划机器学习的情感识别API,能够帮助不同平台的开发者轻松添加智能应用,而无需精通人工智能领域.牛津计划仅仅是微软在人工智能领域探索中的一个实例,而我们的期望是实现更加注重个人使 ...

  8. pt-find使用

    查找MySQL的表,并且做一些操作,基本语法就如下: pt-find [OPTIONS] [DATABASES] (1)查找一天前建立的MyISAM 引擎的表 [root@mxqmongodb2 bi ...

  9. 【Leetcode】【Medium】Rotate Image

    You are given an n x n 2D matrix representing an image. Rotate the image by 90 degrees (clockwise). ...

  10. 【转】Java中的String,StringBuilder,StringBuffer三者的区别

    https://www.cnblogs.com/su-feng/p/6659064.html 最近在学习Java的时候,遇到了这样一个问题,就是String,StringBuilder以及String ...