[原] GLES在iOS和Android上的不同
本来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上的不同的更多相关文章
- 关于Unity程序在IOS和Android上显示内嵌网页的方式
近期因为有须要在Unity程序执行在ios或android手机上显示内嵌网页.所以遍从网上搜集了一下相关的资料.整理例如以下: UnityWebCore 从搜索中先看到了这个.下载下来了以后发现这个的 ...
- 解决Lightmap在PC上与ios和Android上表现不同的问题
Lightmap在PC上与android和ios的区别以及解决方法 1. 问题描述 相信很多人碰到过Lightmap的一些问题: 烘培好Lightmap之后,在PC上看起来相当给力,而打包成ios或 ...
- cocos打包到ios与android上音频推荐
首先贴一张官方对于ios与android上音频格式的推荐: 这里只给出了推荐格式,一般我们在实际运用中会使用如下方式: 一.IOS与安卓各一套:音乐:都使用MP3 音效:ios用caf Andr ...
- 如何让音频跟视频在ios跟android上自动播放
如何让音频跟视频在ios跟android上自动播放 <audio autoplay ><source src="audio/alarm1.mp3" type=&q ...
- 【转】iOS类似Android上toast效果
原文网址:http://m.blog.csdn.net/article/details?id=50478737 做过Android开发的人都知道toast,它会在界面上显示一排黑色背景的文字,用于提示 ...
- input,textarea在ios和Android上阴影和边框的处理方法(在移动端)
1.去掉ios上阴影的方法只需要在css文件上添加input,textarea{-webkit-appearance: none;}就可以了 2.在移动端上input和textarea边框问题,也是在 ...
- 移动端跨平台应用开发(ios、Android、web)- Flutter 技术
关键词:Google 出品:Dart语言:Flutter Engine引擎:响应式设计模式:原生渲染:免费并且开源 一.简介 Flutter 是谷歌2018年发布的跨平台移动UI框架.作为谷歌的开源移 ...
- 在MAC上搭建cordova3.4.0的IOS和android开发环境
Hello,大家好,今天给大家说说在mac上搭建cordova3.4.0的iOS和Android开发环境,首先下载cordova,地址:https://cordova.apache.org/#down ...
- android 和iOS的view上的区别
android上的view的类叫View, 以下是它的class overview, This class represents the basic building block for user i ...
随机推荐
- iOS-单例模式-使用技巧
SingleModel-单例模式 单例可以保证在程序运行过程,一个类只有一个实例(一个对象) 一般将单例设置成宏,这样在使用的时候可以很方便. 我们可以按照下面的步骤实现单例 1.自定义一个.h文件, ...
- (转)[转]大数据时代的 9 大Key-Value存储数据库
在过去的十年中,计算世界已经改变.现在不仅在大公司,甚至一些小公司也积累了TB量级的数据.各种规模的组织开始有了处理大数据的需求,而目前关系型数据库在可缩放方面几乎已经达到极限. 一个解决方案是使用键 ...
- struts2指定集合元素的泛型
public class LoginAction implements Action{ private List users; public void setUsers(List users){ th ...
- POJ 2287 Tian Ji -- The Horse Racing(贪心)
题意:田忌和齐王有n匹马,进行n局比赛,每局比赛输者给胜者200,问田忌最多能得多少钱. 分析:如果田忌最下等的马比齐王最下等的马好,是没必要拿最下等的马和齐王最好的马比的.(最上等马同理) 因此,如 ...
- Difference between ref and out parameters
Original link: http://www.dotnet-tricks.com/Tutorial/csharp/K0Hb060414-Difference-between-ref-and-ou ...
- 转:Android studio Gradle
提高Android Studio中Gradle执行效率 分类: android studio2015-06-26 11:54 2374人阅读 评论(2) 收藏 举报 android studiogra ...
- Window 8.1 计时器功能及图片切换
<Canvas Margin="450,0" Width="795" Grid.Column="1"> <Image Ma ...
- .NET研发人员面试题(二)
1.当使用new BB()创建BB的实例时,产生什么输出? public class AA { public AA() { PrintFields(); } public virtual void P ...
- OS X EI Capitan安装mcrypt
OS X EI Capitan安装mcrypt (我的博客原文:http://www.jmolboy.com/2015/12/01/mcrypt-extension-on-EI-Capitan/) ...
- php 获取链接参数
private function getQuerystr($url,$key){ $res = ''; $a = strpos($url,'?'); if($ ...