OpenGL ES 响应屏幕旋转 iOS
iOS下使用OpenGL 如果使用GLKit View 那么不用担心屏幕旋转的问题,说明如下:
If you change the size, scale factor, or drawable properties of a GLKit view, it automatically deletes and re-creates the appropriate framebuffer objects and renderbuffers the next time its contents are drawn.
GLKit view 自动设置好了 framebuffer 和 renderbuffer 对象,使用者直接设置具体的OpenGL 参数即可。但是GLKit view 在iOS10 下存在一些问题,不能使用,只能继承最简单的UIView,那么所有相关的设置都需要自己完成。
屏幕旋转时需要做的事
现在要自己处理屏幕旋转的事件。这一部分主要讲在屏幕旋转后我们需要做什么事情来让原来的图像以新的屏幕尺寸显示出来。如果参考Android的设计,解决思路就是在屏幕旋转的时候将所有的对象销毁再根据当前的屏幕状态重新创建。简单粗暴但是效率不行。我想不销毁对象的情况下,直接重新设置宽高数据让OpenGL绘制出正确的图像。于是我调用了如下的函数:
glViewport(0, 0, (GLsizei) (size.width * scale), (GLsizei) (size.height * scale));
_renderController->InitUniforms((int) (size.width * scale), (int) (size.height * scale));
首先设置viewport 然后第二行 InitUniforms
函数具体做的事情就是重新设置投影矩阵。很遗憾,这样的做法没有效果,将屏幕从竖屏旋转到横屏时,得到的结果如下:
上半部分什么也没有,下半部分扭曲严重。
问题出在 renderbuffer
Yes, the renderbuffer must be recreated when the interface is rotated, and set to the new size.
所以还需要重新创建renderbuffer,
// first DELETE buffers
glDeleteRenderbuffers(...);
glDeleteFramebuffers(...);
// recreate
glGenFramebuffers(1, &_framebuffer);
glGenRenderbuffers(1, &_renderbuffer);
// bind buffer and set framebuffer and renderbuffer...
具体代码可以参考Recreating the render buffer causes a crash on 3GS device (OpenGL ES 1.1)
在何处做上述的事情?
这一部分讲如何编码来准确监听屏幕旋转事件,来插入上面的那些代码。我们自定义我们的view(UIView),上级的view controller使用 [self.view addSubview:_subView];
来将自定义view加进来。但是当旋转的事件通知到上级的view controller时, 他没有办法去通知subview。我们要自己找个时间点去通知底下的subview.看官方文档:
Instead, rotations are treated as a change in the size of the view controller’s view and are therefore reported using the
viewWillTransitionToSize:withTransitionCoordinator:
method. When the interface orientation changes, UIKit calls this method on the window’s root view controller. That view controller then notifies its child view controllers, propagating the message throughout the view controller hierarchy.The
viewWillLayoutSubviews
method is also called after the view is resized and positioned by its parent.
如果你需要监听旋转从开始之前到结束的整个过程,推荐使用viewWillTransitionToSize:withTransitionCoordinator: 用法示例:
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id <UIViewControllerTransitionCoordinator>)coordinator
{
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
// Code here will execute before the rotation begins.
// Equivalent to placing it in the deprecated method -[willRotateToInterfaceOrientation:duration:]
[coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {
// Place code here to perform animations during the rotation.
// You can pass nil or leave this block empty if not necessary.
} completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {
// Code here will execute after the rotation has finished.
// Equivalent to placing it in the deprecated method -[didRotateFromInterfaceOrientation:]
}];
}
来自 SO What is the “right” way to handle orientation changes in iOS 8?
另外一个,旋转完成后,调用 viewWillLayoutSubviews
方法。很有意思,上面的方法的 completion 回调也是在旋转完成以后被调用的,那么用哪个更合适呢?我自己试验了一下,会早于comletion回调,这个方法其实是在上级的view将要去layoutSubview的时候调用的,还没有完成呢!而且实践表明,如果在comletion回调中做,其实是错误的图像已经显示出来了,然后又去改变他,这里的最终的旋转效果就很糟糕了。
我的代码如下:
/**
Called just after the view controller's view's layoutSubviews method is invoked.
*/
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
_subView.frame = self.view.frame;
[_subView layoutIfNeeded];
}
设置subview的frame尺寸以后,强制让他layout,会调用到subView自己的layoutSubviews
方法,在里面做具体的操作即可。
值得参考的文档,来自大神,目前还是草稿状态:【草稿】iOS OpenGL ES 3 编程 2:绘制三角形、屏幕旋转与架构设计
OpenGL ES 响应屏幕旋转 iOS的更多相关文章
- OpenGL ES: (5) OpenGL的基本概念、OpenGL ES 在屏幕产生图片的过程、OpenGL管线(pipeline)
一. OpenGL的基本概念 OpenGL 的结构可以从逻辑上划分为下面 3 个部分: 图元(Primitives) 缓冲区(Buffers) 光栅化(Rasterize) 图元(Primitives ...
- OpenGL ES: iOS 自定义 UIView 响应屏幕旋转
iOS下使用OpenGL 如果使用GLKit View 那么不用担心屏幕旋转的问题,说明如下: If you change the size, scale factor, or drawable pr ...
- Android OpenGL ES 开发(七): OpenGL ES 响应触摸事件
像旋转三角形一样,通过预设程序来让对象移动对于吸引注意是很有用的,但是如果你想让你的OpenGL图形有用户交互呢?让你的OpenGL ES应用有触摸交互的关键是,扩展你的GLSurfaceView的实 ...
- iOS 平台开发OpenGL ES程序注意事项
本人最近从Android平台的OpenGL ES开发转到iOS平台的OpenGL ES开发,由于平台不同,所以开发中会有一些区别,再次列出需要注意的几点. 1.首先需要了解iOS主要开发框架,再次仅介 ...
- [置顶] 使用Android OpenGL ES 2.0绘图之五:添加运动
传送门 ☞ 系统架构设计 ☞ 转载请注明 ☞ http://blog.csdn.net/leverage_1229 传送门 ☞ GoF23种设计模式 ☞ 转载请注明 ☞ http://blog.csd ...
- [OpenGL ES 02]OpenGL ES渲染管线与着色器
[OpenGL ES 02]OpenGL ES渲染管线与着色器 罗朝辉 (http://www.cnblogs.com/kesalin/) 本文遵循"署名-非商业用途-保持一致"创 ...
- 短视频图像处理 OpenGL ES 实践
2017年,短视频正以其丰富的内容表现力和时间碎片化的特点,快速崛起,而短视频最具可玩性之处就在支持人脸识别的动态贴图和各种不同效果的美颜.滤镜等.那短视频动态贴纸.滤镜.美颜等功能究竟是如何实现的呢 ...
- Android屏幕旋转
一个手机最基本的旋转方向有上面4种,而在Android开发中,涉及到屏幕旋转的地方很多,而且各个函数给出的角度值都不一样,比如 Activity的getRotate,Camera的setDisplay ...
- 梳理 Opengl ES 3.0 (一)宏观着眼
Opengl ES 可以理解为是在嵌入式设备上工作的一层用于处理图形显示的软件,是Opengl 的缩水版本. 下图是它的工作流程示意图: 注意图中手机左边的EGL Layer Opengl ES是跨平 ...
随机推荐
- iSwifting社区【www.iSwifting.com】招聘版主
iSwifting社区[www.iSwifting.com]昨天找来几个主持人.我已经被任命为他们的任务领域. 他们有百度的project噢,还有cocoaChina问答区的活跃人物! 欢迎大家一起学 ...
- Vs2010中水晶报表引用及打包
原文:Vs2010中水晶报表引用及打包 转自:http://yunhaifeiwu.iteye.com/blog/1172283 Vs2010中水晶报表引用 在sap官网中下载支持vs 2010中的水 ...
- Ajax实现在textbox中输入内容,动态从数据库中模糊查询显示到下拉框中
功能:在textbox中输入内容,动态从数据库模糊查询显示到下拉框中,以供选择 1.建立一aspx页面,html代码 <HTML> <HEAD> <title>We ...
- Add GUI to connect to SQL
(*********************************************************************************) (* *) (* Below i ...
- javascript转换.net DateTime方法 (比如转换\/Date(1426056463000)\/)
function getDate(str_time) { var re = new RegExp('\\/Date\\(([-+])?(\\d+)(?:[+-]\\d{4})?\\)\\/'); va ...
- PLinq
PLinq(Linq的并行计算) 上面介绍完了For和ForEach的并行计算盛宴,微软也没忘记在Linq中加入并行计算.下面介绍Linq中的并行计算. 4.0中在System.Linq命名空间下加入 ...
- HAProxy+apache实现web服务动静分离
HAProxy提供高可用性.负载均衡以及基于TCP和HTTP应用的代理,支持虚拟主机,它是免费.快速并且可靠的一种解决方案. HAProxy提供高可用性.负载均衡以及基于TCP和HTTP应用的代理,支 ...
- 微软 PowerShell Script Explorer
微软 PowerShell Script Explorer 满血复活,正式发布 一年前的今天,微软在其Windows PowerShell官方博客声明中止 ‘Script Explorer’ 应用程序 ...
- 单点登录(SSO)实现方式
谁都能看懂的单点登录(SSO)实现方式(附源码) SSO的基本概念 SSO英文全称Single Sign On(单点登录).SSO是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用 ...
- 2014.3.4-C语言学习小结
位操作: 知识点: 1.位运算符 2.位移运算符 1.将指定位设置为12.将指定位设置为03.获取指定位的内容 ==========================复习二进制 1.二进制转换 10-- ...