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是跨平 ...
随机推荐
- selenium2入门 定位 窗体切换等等 (二)
定位用的html素材有两个 demo.html <html> <head> <title>UI Automation Testing</title> & ...
- CRT
G - 中国剩余定理 Time Limit:1000MS Memory Limit:10000KB 64bit IO Format:%I64d & %I64u Submit S ...
- 微软BI 之SSIS 系列 - 使用 Script Task 访问非 Windows 验证下的 SMTP 服务器发送邮件
原文:微软BI 之SSIS 系列 - 使用 Script Task 访问非 Windows 验证下的 SMTP 服务器发送邮件 开篇介绍 大多数情况下我们的 SSIS 包都会配置在 SQL Agent ...
- svn外网访登录不进去提示证书错误Authorization Required
为了外网能访问内网svn.于是坐在外网端口映射.但是奇怪的是内网能访问,外网总也登录不进去.以为是浏览器版本低 但是其他浏览器也一样.最后客户端也登录不进去.提示报错: Authorization ...
- 第三方控件netadvantage UltraWebGrid总结
1.个人习惯前台绑定好实体字段,禁止自动生成:一些属性设置:AutoGenerateColumns="false" <igtbl:UltraWebGrid ID=" ...
- Build MySQL 5.7.4 in RedHat
Install Cmake 1. download cmake source code at http://www.cmake.org/files/v3.1/cmake-3.1.0.tar.gz 2 ...
- 尝试使用Memcached
尝试使用Memcached遇到的狗血问题 乘着有时间,尝试下利用Memcached进行分布式缓存,其中遇到了不少问题及狗血的事情,开篇记录下,希望对您有帮助. 我之前的项目为:Asp.Net MV ...
- C#中几个经常犯的错误总汇
在我们平常编程中,时间久了有时候会形成一种习惯性的思维方式,形成固有的编程风格,但是有些地方是需要斟酌的,即使是一个很小的错误也可能会导致昂贵的代价,要学会善于总结,从错误中汲取教训,尽量不再犯同样错 ...
- 利用MARQUEE实现正在处理效果
ASP.NET服务器端事件利用MARQUEE实现正在处理效果 前言:ASP.NET同仁们应该都遇到过当触发一个比较耗时的服务器端事件时,页面会处在一个等待的状态(即假死状态),用户体验非常不好,很 ...
- 欧几里德算法及其扩展(推导&&模板)
有关欧几里德算法整理: 1.一些相关概念: <1>.整除性与约数: ①一个整数可以被另外一个整数整除即为d|a(表示d整除a,通俗的说是a可以被d整除),其含义也可以说成,存在某个整数k, ...