本来GLES提供了与native platform的接口 EGL,

然而iOS没有使用EGL接口, 而是自己搞了一套,叫做EAGL的类似东西, 虽然说大同小异,但是在做跨平台的时候还是很恶心.

elgMakeCurrent: 默认的EGL是需要surface和display的, iOS的EAGL实现, 对于用户(程序猿)来说, 没有surface和display这些东西.

iOS 下需要使用FBO + RBO, 然后直接通过native API: EAGLContext - presentRenderbuffer,将RBO的内容填充到目标窗口表面.

然而Android的GLES2.0下面, 如果使用了FBO + RBO, 那么只能用于离线渲染,离线读写, 没有任何copy和swap/present接口可以将RBO swap到窗口表面.

http://www.khronos.org/opengles/sdk/docs/man/xhtml/glBindFramebuffer.xml:

Application created framebuffer objects (i.e. those with a non-zero name) differ from the default window-system-provided framebuffer in a few important ways. First, they have modifiable attachment points for a color buffer, a depth buffer, and a stencil buffer to which framebuffer attachable images may be attached and detached. Second, the size and format of the attached images are controlled entirely within the GL and are not affected by window-system events, such as pixel format selection, window resizes, and display mode changes. Third, when rendering to or reading from an application created framebuffer object, the pixel ownership test always succeeds (i.e. they own all their pixels). Fourth, there are no visible color buffer bitplanes, only a single "off-screen" color image attachment, so there is no sense of front and back buffers or swapping. Finally, there is no multisample buffer, so the value of the implementation-dependent state variables GL_SAMPLES and GL_SAMPLE_BUFFERS are both zero for application created framebuffer objects.

虽然GLES3.0 有glBlitFramebuffer(),可以直接将自己的FBO复制到context的默认FBO( fboID = 0)上,然后swap, 但是显然目前的目标平台是GLES2.0. 所以现在对于安卓有两个方案: 1.使用默认FBO,放弃自定义的FBO和RBO. 2.使用自定义FBO+RenderTexture, 最后使用full screen quad把这张texture绘制到默认FBO上,然后swap.

很显然从效率上说,第一种好,因为第二种需要额外的内存开销,并且有多余的draw call,还多了一次纹理采样.但是最后可能要综合兼容性/适配性等其他因素, 选择最终方案.

On iOS, we use FBO and RBO to draw to the RBO, and use presentBuffer to swap the content of RBO to window surface(or layer).

but on Android GLES 2.0, still you can attach a RBO to your own FBO and render onto it, but there's no way that you can copy/swap your RBO to window surface.

although in GLES3.0 the glBlitFramebuffer is finally available, which can copy your own FBO to the default FBO( fboID = 0), and then yiou can swap it, that turns out not a sound solution since we're now targeting the GLES 2.0 platform.
Now we have 2 solutions: 1.to use the default FBO (0), and no other custom FBOs. 2. use own FBO, and RenderTexture instead of RBO, and finally draw the texture onto the default FBO via a full screen quad, and then swap it.
I believe the former one is better in performance because the latter one takes more memory and, uses extra draw call & texture sampling. But the compatiblity & adaptability also needs to be considered.


补充:

GL Extensions:  iOS每一代的硬件是固定的, 所以extension基本是固定的. 但是Android上由于显示芯片可以随厂家来配, 所以比较繁琐. 所以整体的开发上, iOS有点像console平台,比如XBOX, 而Android更像PC平台,需要考虑各种CPU/GPU/等等问题.

对于前面FBO的问题, 由于不使用FBO的话,灵活性就大大降低.而且等于关闭了RenderToTexture的特性, 当然可以只有在RenderToTexture的时候才绑定FBO, 正常渲染使用默认FBO, 但是这样看起来不够elegant(也许还好吧), 而且对于现有的架构有一定的改动. 所以目前暂用的方案是使用FBO, 用RenderTexture作为backbuffer, 最后再绘制到默认FBO上,已经测试通过.
如果以后有时间做后续优化的话,可能这么做: 用默认FBO, RenderToTexture的时候再绑定自己的FBO.


FBO不适合动态改变attachment, 如果有多个rendertarget, 那么就用多个FBO, 挂接到render target上.

动态attach buffer的效率相对要低.

2014/12/20 更新一些细节:

在iOS上, 即使OpenGLES 2.0的设备和API, 也支持一些3.0才有的特性, 2.0上或许有扩展, 但是都是各个厂商各自为战, 非常不方便.

1.Multisample (https://www.khronos.org/registry/gles/extensions/APPLE/APPLE_framebuffer_multisample.txt)

虽然它是Extension, 但是在iOS上是直接可以用的. 即RenderbufferStorageMultisampleAPPLE.

在android GLES 2.0上的Imagenation的Extension:

https://www.khronos.org/registry/gles/extensions/IMG/IMG_multisampled_render_to_texture.txt

因为是Imagenation(IMG)的扩展, 估计只能在PowerVR的GPU上才有.

2.MAXMIPLEVEL

https://www.khronos.org/registry/gles/extensions/APPLE/APPLE_texture_max_level.txt

这个GLES 2.0上只有扩展, 3.0才有. 但是iOS上也是固有的,即TEXTURE_MAX_LEVEL_APPLE, 其他平台就不一定了.

另外工作中发现某设备, 搭载的是GLES 3.0 capable的GPU, 但是是2.0的driver, 发现mipmap chain如果不完整(0-n)的话, 贴图采样会变成黑色, 这个是2.0的通病, 但是iOS上可以正常显示, 应该是2.0的spec不够清晰.

通过hack: 强制使用OpengGL ES 3.0的GL_TEXTURE_MAX_LEVEL / GL_TEXTURE_BASE_LEVEL, 竟然也能成功, 贴图就不黑了...
还有就是在这种设备上强制使用ETC2 (2.0的header, ETC2用的是3.0header里面ETC贴图对应的数字), 竟然也是可以的.

3.iOS上可以说有固定的贴图格式: PVRTC. 因为他用的全部都是PVR(PowerVR)的GPU. 而android的GLES 2.0上各种压缩贴图格式ATITC, ASTC, ETC1, PVRTC, S3TC...

虽然ETC1支持的最广泛, 但是ETC1压缩不支持alpha通道....需要单独加一张alpha贴图, 或者其他处理方式:
http://malideveloper.arm.com/cn/develop-for-mali/sample-code/etcv1-texture-compression-and-alpha-channels/

上面的前两个问题虽然恶心, 但是花时间总能找到渲染错误的原因, 而且有相对简单的解决方案. 但这个压缩纹理的问题才是是最头疼的问题.

所以目前我们的产品(大型3D游戏 :P)暂时只支持OpenGL ES 3.0的设备, 因为3.0对于压缩贴图格式,有了统一的标准: ETC2. 它支持alpha通道. 还有单通道和双通道压缩格式(specular/normal map等).

另外一种方案是使用in-game-download, 根据设备的特性下载对应的资源包, 需要生成n种资源包.
我们没有这么做是因为除了贴图的问题以外, OpenGLES 2.0上shader的bug也非常多, 这个不知道是compiler的bug, 还是渲染的问题:

同样的shader在iOS上没有问题, 但在android设备上, 总会遇到问题, 比如屏幕上有黑块, 或者某个shader渲染不对, 稍微改成其他等价的方式就好了, 比如之前贴过的bug:

 //GLES2.0 fragment shader

 float   factor   = ( dir >=  ) ?  : ;   //doesn't work! artifacts!
float factor = step(, dir); //f*******k! it works! the hell why?

改用3.0以后问题全好了. 所以说OpenGL ES 2.0 不适合做大型3D游戏. 至少是android上的不适合, 至少是目前不适合.

其他类似的问题应该还有很多, 比如iOS上固有glDiscardFramebufferEXT, 但是android仍然是Extension(https://www.khronos.org/registry/gles/extensions/EXT/EXT_discard_framebuffer.txt)

其他的暂时想不起来了.

[原] GLES在iOS和Android上的不同的更多相关文章

  1. 关于Unity程序在IOS和Android上显示内嵌网页的方式

    近期因为有须要在Unity程序执行在ios或android手机上显示内嵌网页.所以遍从网上搜集了一下相关的资料.整理例如以下: UnityWebCore 从搜索中先看到了这个.下载下来了以后发现这个的 ...

  2. 解决Lightmap在PC上与ios和Android上表现不同的问题

    Lightmap在PC上与android和ios的区别以及解决方法 1.  问题描述 相信很多人碰到过Lightmap的一些问题: 烘培好Lightmap之后,在PC上看起来相当给力,而打包成ios或 ...

  3. cocos打包到ios与android上音频推荐

    首先贴一张官方对于ios与android上音频格式的推荐: 这里只给出了推荐格式,一般我们在实际运用中会使用如下方式: 一.IOS与安卓各一套:音乐:都使用MP3    音效:ios用caf Andr ...

  4. 如何让音频跟视频在ios跟android上自动播放

    如何让音频跟视频在ios跟android上自动播放 <audio autoplay ><source src="audio/alarm1.mp3" type=&q ...

  5. 【转】iOS类似Android上toast效果

    原文网址:http://m.blog.csdn.net/article/details?id=50478737 做过Android开发的人都知道toast,它会在界面上显示一排黑色背景的文字,用于提示 ...

  6. input,textarea在ios和Android上阴影和边框的处理方法(在移动端)

    1.去掉ios上阴影的方法只需要在css文件上添加input,textarea{-webkit-appearance: none;}就可以了 2.在移动端上input和textarea边框问题,也是在 ...

  7. 移动端跨平台应用开发(ios、Android、web)- Flutter 技术

    关键词:Google 出品:Dart语言:Flutter Engine引擎:响应式设计模式:原生渲染:免费并且开源 一.简介 Flutter 是谷歌2018年发布的跨平台移动UI框架.作为谷歌的开源移 ...

  8. 在MAC上搭建cordova3.4.0的IOS和android开发环境

    Hello,大家好,今天给大家说说在mac上搭建cordova3.4.0的iOS和Android开发环境,首先下载cordova,地址:https://cordova.apache.org/#down ...

  9. android 和iOS的view上的区别

    android上的view的类叫View, 以下是它的class overview, This class represents the basic building block for user i ...

随机推荐

  1. asp.net 客户邮件群发功能 SendMail 发送静态化html

    背景:现在几乎每个企业都要用到邮箱,而在大客户量情况下,为我们的不同等级的客户送上节日关怀,以及把我们的喜讯.新品通知到他们是我们急需解决的问题.效果如图 思路: 1.静态化网页模版,首先考虑需要发送 ...

  2. WCF之绑定

    NameSpace+Name作为服务元数据的唯一标示.BindingElement描述Binding的特征. 绑定表示通信信道的配置,定义C/S间的协议. 分为:传输信道(TCP,HTTP…),消息编 ...

  3. 2016.10.30 济南学习 Day2 下午 T1

    他 [问题描述] 一张长度为N的纸带,我们可以从左至右编号为0 − N(纸带最左端标号为 0).现在有M次操作,每次将纸带沿着某个位置进行折叠,问所有操作之后纸带 的长度是多少. [输入格式] 第一行 ...

  4. C++ Strings(字符串)

    Constructors 构造函数,用于字符串初始化 Operators 操作符,用于字符串比较和赋值 append() 在字符串的末尾添加文本 assign() 为字符串赋新值 at() 按给定索引 ...

  5. 死亡之ping(Ping of Death)

    最简单的基于IP的攻击可能要数著名的死亡之ping,这种攻击主要是由于单个包的长度超过了IP协议规范所规定的包长度.产生这样的包很容易,事实上,许多操作系统都提供了称为ping的网络工具.在为Wind ...

  6. age

    #include<iostream> #include<math.h> #define pi 3.14 using namespace std; int main() { in ...

  7. 将mysql的查询结果输出到文件

    在sql命令中我们可以查询到前数行的表,同时也可以将查询结果输出到txt文档 语句:select * from tablename into outfile 'filename.txt'; 例如:se ...

  8. linux服务器修改ssh默认22端口方法

    1.登录服务器,打开sshd_config文件 # vim /etc/ssh/sshd_config 2.找到#Port 22,默认是注释掉的,先把前面的#号去掉,再插入一行设置成你想要的端口号,注意 ...

  9. 下拉刷新--第三方开源--PullToRefresh

    效果预览图: 下载地址:https://github.com/chrisbanes/Android-PullToRefresh activity_main.xml: <RelativeLayou ...

  10. 【面试虐菜】—— LVS负载均衡

    Load Balancer(负载均衡器): Load Balancer是整个集群系统的前端,负责把客户请求转发到Real Server上.Load Balancer通过Ldirectord监测各Rea ...