android 离屏渲染 简单书,Android OpenGL ES 8.FrameBuffer离屏渲染
作用
FrameBuffer Object,也称FBO,离屏渲染,可以摆脱屏幕的束缚,在后台做图像处理。
理解
FrameBuffer和Texture绑定,FrameBuffer犹如画板,而Texture犹如画纸,我们在上面画东西,画完后,我们可以拿Texture去绘制到其他地方上面。
(本文重点:这个是我个人对FBO的理解,也是帮助我去使用它的方式。如果有更好的理解方式,可以留言沟通。)
代码
本章案例效果是在屏幕外绘制一张图片,并保存到本地。
由于GL运行需要EGL环境,而GLSurfaceView已经帮我们构建了这样的一个环境,所以我们此次也是在GLSurfaceView上运行,但是不绘制到屏幕上。
案例为试验效果,只绘制一帧,所以就放到onDrawFrame上运行,读者之后可以根据自己的需求,处理好相关的生命周期。
public void onDrawFrame(GL10 glUnused) {
GLES20.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
// 1. 创建FrameBuffer、纹理对象
createEnv();
// 2. 配置FrameBuffer相关的绘制存储信息,并且绑定到当前的绘制环境上
bindFrameBufferInfo();
// 3. 更新视图区域
GLES20.glViewport(0, 0, mTextureBean.getWidth(), mTextureBean.getHeight());
// 4. 绘制图片
drawTexture();
// 5. 读取当前画面上的像素信息
readPixels(0, 0, mTextureBean.getWidth(), mTextureBean.getHeight());
// 6. 解绑FrameBuffer
unbindFrameBufferInfo();
// 7. 删除FrameBuffer、纹理对象
deleteEnv();
}
以上就是关键代码,相比之前其他章节,这里多出了1、2、6、7这几个关键步骤。
步骤1. 创建FrameBuffer、纹理对象
private int[] mFrameBuffer = new int[1];
private int[] mTexture = new int[1];
private void createEnv() {
// 1. 创建FrameBuffer
GLES20.glGenFramebuffers(1, mFrameBuffer, 0);
// 2.1 生成纹理对象
GLES20.glGenTextures(1, mTexture, 0);
// 2.2 绑定纹理对象
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTexture[0]);
// 2.3 设置纹理对象的相关信息:颜色模式、大小
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA,
mTextureBean.getWidth(), mTextureBean.getHeight(),
0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
// 2.4 纹理过滤参数设置
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
// 2.5 解绑当前纹理,避免后续无关的操作影响了纹理内容
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
}
创建纹理和之前的没有差别,而创建Framebuffer也很简单。
步骤2. 配置FrameBuffer相关的绘制存储信息,并且绑定到当前的绘制环境上
private void bindFrameBufferInfo() {
// 1. 绑定FrameBuffer到当前的绘制环境上
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFrameBuffer[0]);
// 2. 将纹理对象挂载到FrameBuffer上,存储颜色信息
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0,
GLES20.GL_TEXTURE_2D, mTexture[0], 0);
}
这里先将FrameBuffer绑定到当前的绘制环境上,所以,在没解绑之前,所有的GL图形绘制操作,都不是直接绘制到屏幕上,而是绘制到这个FrameBuffer上!
若想要解绑,想直接绘制到屏幕上,则可以通过GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);实现。
第二步是将FrameBuffer和纹理对象相关联,纹理存储绘制到FrameBuffer上的颜色信息,代码也很简单。
步骤6. 解绑FrameBuffer
private void unbindFrameBufferInfo() {
// 解绑FrameBuffer
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
}
解绑,之后的绘制操作都是直接绘制到屏幕上。
步骤7. 删除FrameBuffer、纹理对象
private void deleteEnv() {
GLES20.glDeleteFramebuffers(1, mFrameBuffer, 0);
GLES20.glDeleteTextures(1, mTexture, 0);
}
注意
FrameBuffer每次绘制都会得到一个水平镜像翻转的视图,要处理这个问题,可以在绘制的时候添加一个翻转矩阵,或者,用FrameBuffer绘制2次。
总结
本章使用FrameBuffer实现了离屏渲染,并且将FrameBuffer上的绘制信息保存成Bitmap到本地(此处省略,详细可以看GitHub工程),而FrameBuffer除了这个作用外,还可以将离屏渲染好的图片再绘制到屏幕上,而不用绘制到本地,毕竟我们绘制后得到一个Texture,那就有发挥的空间。比如我们要做的效果是屏幕上画一个背景,背景上有朵花,一共2张图,但背景要做滤镜处理,而花不用,那么,我们可以将背景通过FrameBuffer去做滤镜处理,然后得到一个纹理,直接绘制到屏幕上,而花直接绘制,那么就得到想要的效果了。具体留给读者作为练习题。
后记
该篇文章是差不多半年前就写好的文章,不过觉得写得比较简陋,缺少一些图片来生动形象地去描述这个概念,也怕自己的局限误导了读者。不过由于有读者好奇追问,所以就勉强放上来。文中若有疏漏、误导,请指出。
阅读资料
其他
本系列课程所有相关代码请参考我的GitHub项目⭐GLStudio⭐,喜欢的请给个小星星。
android 离屏渲染 简单书,Android OpenGL ES 8.FrameBuffer离屏渲染相关推荐
- SDL2源码分析之OpenGL ES在windows上的渲染过程
SDL2源码分析之OpenGL ES在windows上的渲染过程 更新于2018年11月4日. 更新于2018年11月21日. ffmpeg + SDL2实现的简易播放器 ffmpeg和SDL非常强大 ...
- Android技术应用实验指导书,Android应用开发实验指导书
第 1 页手机应用开发实验指导书西南科技大学计算机科学与技术学院2015.11第 2 页目录手机应用开发 .1实验指导书 .1实验一:搭建 Android开发平台和创建 HelloWorld程序 .- ...
- android 流星动画,超简单的android 流星雨动画 流星动画
1.直接看效果 2.布局文件 xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http: ...
- OpenGL ES之基本简介和渲染流程
简介 OpenGL ES (OpenGL for Embedded Systems) 是以⼿持和嵌入式为目标的高级3D图形应用程序编程接口(API). OpenGL ES是目前智能手机中占据统治地位的 ...
- android漫画app代码,漫画书Android客户端 – ComicApp
漫画书 1.平台:Android客户端(后期完善IOS端) 2.开发框架:React Native react-redux react-thunk 3.开发工具:Vs Code 1.8 1.项目架构 ...
- Android动态日志,一个简单的Android日志类
Android自带的日志类不支持显示文件名和行号,调试时很不方便.而第三方日志库往往又太重.所以自己对Android自带的日志类做了一个简单的封装,主要是调试时使用,不考虑日志丢失和性能问题.日志的输 ...
- android沉浸式模式简书,Android 沉浸式模式与常见状态栏和导航栏效果
Android沉浸式模式 官方称沉浸式状态栏为沉浸式模式. 什么是沉浸式? 沉浸式就是让人专注当前的(由设计者营造)情境下感到愉悦和满足,而忘记真实的情境. 什么是Android中的沉浸式? 当启用该 ...
- android源码编译 简书,android学习笔记之源码编译
编译环境 1.需要Ubuntu 64bit,建议Ubuntu14.04 64-bit 2.安装openJDK7 $ sudo apt-get update $ sudo apt-get install ...
- android+包+反编译,简单的Android之apk包反编译方法
网上相关的文章一大堆了,我只是总结下自己的反编译方法和工具 工具下载地址: 下载上面的三个工具的压缩包 Apktool_v1.5.1_CHS_By_b-sf.rar dex2jar.zip jd-gu ...
最新文章
- SQL Server-创建表格、各种约束条件
- tcpdump抓包命令_tcpdump实战
- 重构——30以类取代类型码(Replace Type Code with Class)
- 深度学习导论(5)手写数字识别问题步骤
- java国家电网面试试题_国家电网笔试面试相关
- Reporting Services Catalog Database File Existence error during installing SQL Server 2008 R2
- 从华住遭遇“抄袭” 看酒店行业互联网发展现状
- 联想年报有看头:供应链展现韧性,PC迎来新机遇
- ZBrush中的法线贴图你知道吗?
- 如何在 5 分钟内成为游戏引擎的行家
- 基于JNA(Java Native Access)实现RFID单卡、多卡读取以及写入。
- Linux wifi hostpad,将你的电脑变身无线路由wifi host, ipad/ipod/手机一起来无线互联吧...
- 从云计算到固态硬盘 颠覆性技术成熟度分析
- linux修改配置文件configure,./configure 的配置和用法
- 计算机闪存大小,电脑内存大小有什么区别
- 海思平台ISP调试经验
- Exception in thread main java.lang.NoSuchMethodError: scala.Predef$.ArrowAssoc(Ljava/lang/Object;)
- 程序猿生存指南-16 农村青年
- Flutter Scaffold
- 麻将胡牌算法思路(任意赖子)
热门文章
- phpstudy mysql 版本_phpStudy中升级MySQL版本到5.7.17的方法步骤
- python以垂直方式输出hello world_python3提问:垂直输出Hello World,全部代码不超过2行....
- 美国教授描述未来学校,将颠覆现有教育模式
- 一次阿里巴巴面试……
- 8万级自动挡智能SUV,舒适好开是亮点,众泰T600Coupe要逆天?
- 为何美洲蝉中意17这个质数?
- linux 打开上一级目录,linux开机启动过程、PATH、过滤一级目录、cd的参数、ls -lrt、命令切割日志...
- 计算机考试演示文稿模板,2018职称计算机考试PowerPoint习题10
- PHP实现RPC(简版)
- #pragma code_seg(INIT)/code_seg(PAGE)