iOS开发-OpenGLES进阶教程4

教程

OpenGLES入门教程1-Tutorial01-GLKit OpenGLES入门教程2-Tutorial02-shader入门 OpenGLES入门教程3-Tutorial03-三维变换 OpenGLES入门教程4-Tutorial04-GLKit进阶 OpenGLES进阶教程1-Tutorial05-地球月亮 OpenGLES进阶教程2-Tutorial06-光线 OpenGLES进阶教程3-Tutorial07-粒子效果 这一次的内容是帧缓存。

概要

帧缓存:接收渲染结果的缓冲区叫做帧缓存。 在OpenGL的渲染管道中,几何数据和纹理通过一系列变换和测试后,变成渲染到屏幕上的二维像素。渲染的目标管道就是帧缓存区。

(In OpenGL rendering pipeline, the geometry data and textures are transformed and passed several tests, and then finally rendered onto a screen as 2D pixels. The final rendering destination of the OpenGL pipeline is calledframebuffer)

每一个iOS原生控件都有一个对应的CoreAnimation层。 CoreAnimation合成器使用OpenGL ES来尽可能高效地控制GPU、混合层和切换帧缓存。 思考:OpenGL ES的渲染结果会放到帧缓存区,如何与视图的显示联系起来?

效果展示

核心思路

如下图,帧缓存像素颜色的输出结果在GL_COLOR_ATTATCHMENT开头的缓存区。 首先,我们用一个纹理缓存来作为OpenGL ES的第一次输出的缓存区,这样我们可以得到一个纹理Texture0。 然后用Texture0作为第二次绘制的纹理,得到最后的结果。

OpenGL的帧缓存

具体细节

  • 弯路

在实现过程中,走过了几个弯路,先提出来,希望后来者不要再重复:

  • 新建上下文。 因为需要拿到第一次渲染的结果-纹理Texture0,就想尝试新建上下文mExtraContext来渲染纹理,然后用原来的上下文mBaseContext来进行接收纹理和渲染。 结果是两个上下文是相互独立的,mExtraContext渲染出来的结果并不能在mBaseContext使用。
  • 使用同一个GLKBaseEffect来渲染纹理Texture0和渲染最后结果。
  • 在渲染纹理Texture0的时候使用不同的视口大小,但是没有调用glviewport()。
  • 把纹理对象关联到帧缓存

1、新建纹理 2、设置纹理格式 3、分配纹理内存 4、新建帧缓存 5、切换帧缓存为纹理对象

GLuint colorTexture;
// 1
glGenTextures(1, &colorTexture);
glBindTexture(GL_TEXTURE_2D, colorTexture);

// 2
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
                GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
                GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
                GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
                GL_LINEAR_MIPMAP_LINEAR);

// 3
glTexImage2D(GL_TEXTURE_2D,
             0,
             GL_RGBA,
             fboWidth,
             fboHeight,
             0,
             GL_RGBA,
             GL_UNSIGNED_BYTE,
             NULL);

//4
glGenFramebuffers(1, &fboName);
glBindFramebuffer(GL_FRAMEBUFFER, fboName);
//5
glFramebufferTexture2D(GL_FRAMEBUFFER,
                       GL_COLOR_ATTACHMENT0,
                       GL_TEXTURE_2D, colorTexture, 0);
  • 渲染缓存关联到帧缓存

1、新建渲染缓存 2、分配渲染内存 3、新建帧缓存 4、切换帧缓存为渲染缓存

//1
glGenRenderbuffers(1, &colorRenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer);
//2
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8_OES, viewport[2],viewport[3]);

//3
glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
//4
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRenderbuffer);

结果解析

先渲染里面锥体,得到的结果作为纹理,进行第二次绘制。观察简化版,下图正方形白色区域为渲染后的纹理。

Paste_Image.png

原图如下。被渲染到一个纹理后,再被显示到屏幕上。

思考

答案:CAEGLayer OpenGL ES会有连接到层,与层分享数据的帧缓存,至少包括一个像素颜色渲染缓存。 CAEAGLLyaer是CoreAnimation提供的标准层类之一,与OpenGL ES的帧缓存共享它的像素颜色仓库。 与一个Core Animation共享内存的像素颜色渲染缓存在层调整大小时会自动调整大小。其他缓存,例如深度缓存,不会自动调整大小。可以在layoutSubviews方法里面删除现存的深度缓存,并创建一个新的与像素颜色渲染缓存的新尺寸相匹配的深度缓存。

总结

这个demo不难,但是很考验对帧缓存的理解。上面的弯路还有包括多个顶点数组、GLKBaseEffect和shader混用等,本来是打算用shader来实现,但是iOS卷 推荐熟练使用GLKBaseEffect,最后还是用的GLKBaseEffect。 学习OpenGL ES对了解iOS的性能优化很有帮助。 现在再看上面那个图,会有不一样的认知。 参考帧缓存 这里有源码

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏程序员宝库

如何用 vue 制作一个探探滑动组件

前言 嗨,说起探探想必各位程序汪都不陌生(毕竟妹子很多),能在上面丝滑的翻牌子,探探的的堆叠滑动组件起到了关键的作用,下面就来看看如何用vue写一个探探的堆叠组...

858130
来自专栏Python疯子

Python 简单实现标签词云

基于Python的词云生成类库,很好用,而且功能强大.博主个人比较推荐 github:https://github.com/amueller/word_clo...

60810
来自专栏电光石火

HTML条件注释判断浏览器及检验

<!--[if !IE]><!--> 除IE外都可识别 <!--<![endif]--> <!--[if IE]> 所有的IE可识别 <![endif]--> ...

44790
来自专栏Grace development

PHP GD库解析一张简单图片并输出

16700
来自专栏十月梦想

html常用标签标记

本博客所有文章如无特别注明均为原创。作者:十月梦想 ,复制或转载请以超链接形式注明转自 十月梦想博客 。 原文地址《html常用标签标记》

23330
来自专栏HTML5学堂

一步步教你弹性框架-下篇

HTML5学堂:本文继续为大家讲解弹性框架,在前两篇文章当中,我们从最基本的来回运动,讲解到缓冲运动、有摩擦力的运动。基本实现了弹性动画效果。今天我们主要来进行...

38040
来自专栏Android群英传

模拟自然动画的精髓——TimeInterpolator与TypeEvaluator

13010
来自专栏偏前端工程师的驿站

CSS魔法堂:小结一下Box Model与Positioning Scheme

前言  对于Box Model和Positioning Scheme中3种定位模式的细节,已经通过以下几篇文章记录了我对其的理解和思考。 《CSS魔法堂:重新...

19260
来自专栏逍遥剑客的游戏开发

Direct3D学习(一):3D Sierpinski镂垫绘制

22090
来自专栏全沾开发(huā)

总结CSS3新特性(Transform篇)

总结CSS3新特性(Transform篇) 概述: CSS3新添加的Transform可以改变元素在可视化区域的坐标(这种改变不会引起...

35470

扫码关注云+社区

领取腾讯云代金券