OpenGL ES: iOS 自定义 UIView 响应屏幕旋转
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
viewWillLayoutSubviewsmethod 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 自定义 UIView 响应屏幕旋转的更多相关文章
- OpenGL ES 响应屏幕旋转 iOS
iOS下使用OpenGL 如果使用GLKit View 那么不用担心屏幕旋转的问题,说明如下: If you change the size, scale factor, or drawable pr ...
- 【Android 应用开发】OpenGL ES 2.0 -- 制作 3D 彩色旋转三角形 - 顶点着色器 片元着色器 使用详解
最近开始关注OpenGL ES 2.0 这是真正意义上的理解的第一个3D程序 , 从零开始学习 . 案例下载地址 : http://download.csdn.net/detail/han120201 ...
- OpenGL ES 2.0 -- 制作 3D 彩色旋转三角形 - 顶点着色器 片元着色器 使用详解
最近开始关注OpenGL ES 2.0 这是真正意义上的理解的第一个3D程序 , 从零开始学习 . 案例下载地址 : http://download.csdn.net/detail/han120201 ...
- IOS开发——手动设置屏幕旋转
在移动开发过程.您可能需要跨越看看你的手机.有可能是所有的接口必须跨越,有可能是一个交叉通过电话,当用户当,你的接口也希望他能跨越.还有可能的是,界面的一部分需要被侧向显示.视情况而定,有不同的方法来 ...
- IOS自定义UIView
IOS中一般会用到几种方式自定义UIView 1.继承之UIView的存代码的自定义View 2.使用xib和代码一起使用的自定义View 3.存xib的自定义View(不需要业务处理的那种) 本文主 ...
- iOs 自定义UIView 日历的实现 Swift2.1
学习Swift有一个月了,动手写一个UIView吧. 所有源代码在最后,直接用就可以了,第一次写Swift,和C#,Java还是有区别的 (博客园可以考虑在代码插入中添加Swift的着色了) 1 函 ...
- Android屏幕旋转
一个手机最基本的旋转方向有上面4种,而在Android开发中,涉及到屏幕旋转的地方很多,而且各个函数给出的角度值都不一样,比如 Activity的getRotate,Camera的setDisplay ...
- ##DAY3 自定义视图、视图控制器、视图控制器指定视图、loadView、 viewDidLoad、MVC、屏幕旋转、内存警告
##DAY3 自定义视图.视图控制器.视图控制器指定视图.loadView. viewDidLoad.MVC.屏幕旋转.内存警告 #pragma mark ———————自定义视图的步骤 —————— ...
- IOS 中openGL使用教程1(openGL ES 入门篇 | 搭建openGL环境)
OpenGL版本 iOS系统默认支持OpenGl ES1.0.ES2.0以及ES3.0 3个版本,三者之间并不是简单的版本升级,设计理念甚至完全不同,在开发OpenGL项目前,需要根据业务需求选择合适 ...
随机推荐
- ajax-json,遇到的一个问题,jquery var ,加载顺序。JS对象,json格式转换。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- php的pid文件指定用户
比如pid文件指定www用户,首先得有这用户和用户组. 找到pathtophp-fpm.conf文件,修改里面得相关内容. 修改listen.owner=www listen.group=www us ...
- python--第十天总结(Select/Poll/Epoll使用 )
首先列一下,sellect.poll.epoll三者的区别 select select最早于1983年出现在4.2BSD中,它通过一个select()系统调用来监视多个文件描述符的数组,当select ...
- 十一 hashlib模块
# 1.什么叫hash:hash是一种算法(3.x里代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法),该算法接受传入的 ...
- centos 7 命令行模式和桌面版之间的切换
CentOS7图形界面与命令行界面切换 在图形界面使用 ctrl+alt+F2切换到dos界面 dos界面 ctrl+alt+F2切换回图形界面 在命令上 输入 init 命令 切换到dos界面 输入 ...
- permissions required by Vibrator.vibrate: android.permission.VIBRATE
<!-- 静止休眠 --><uses-permission android:name="android.permission.WAKE_LOCK" />&l ...
- Spring Boot 整合mybatis 使用多数据源
本人想要实现一个项目里面多个数据库源连接,所以就尝试写一个demo,不多说,先贴结构,再贴代码,可以根据以下的顺序,直接copy解决问题. 首先,dao和resource下的mappers可以用myb ...
- RNA-seq数据综合分析教程 AKAP95
https://blog.csdn.net/l_yivs?t=1 RNA-seq数据综合分析教程 2 4,055 A+ 所属分类:Transcriptomics 收 藏 2 RNA-se ...
- python基础之Day6
一.元组 定义:t=(1,2,3,4) 总结:存多个值,值为任意类型 只有读的需求,没有改的需求 有序,不可变(元组里每个值对应的索引内存地址不能变) 在元素个数相同的情况下,元组比列表更节省空间 二 ...
- python3 第二十四章 - 函数式编程之Anonymous function(匿名函数)
匿名函数指一类无须定义标识符的函数或子程序.Python用lambda语法定义匿名函数,只需用表达式而无需申明.lambda语法的定义如下: lambda [arg1 [,arg2, ... argN ...