CardboardSDK-iOS 源码简单分析
该项目地址: 地址
克隆地址为 https://github.com/rsanchezsaez/CardboardSDK-iOS.git
目前如果想在iOS设备上实现双目VR的功能,Google 已经提供了官方的sdk,上手简单,但是由于在实际使用中有其他需求,GVR的源码无法修改,所以还是使用这个野生的SDK来开发。这篇文章主要就是简单分析一下这个sdk的ViewController 的代码,至于内部的复杂数学计算,暂时无法涉及。
CBDViewController
主要要分析的就是 CBDViewController 这个类,其继承了 GLKViewController 并实现樂 GLKViewControllerDelegate 这个接口。成员:stereoRendererDelegate 负责实现若干个回调函数,比如在Cardboard各个设置完成后进行所需的绘制工作。
1. Init
初始化各个成员变量,设置GLKViewController的delegate为self,启动设备的传感器,开始监听。
2. ViewDidLoad
创建OpenGL的Context 并回调 [self.stereoRendererDelegate setupRendererWithView:self.view] 此时设置Context为 glview.context,可以进行绘制的准备工作,比如创建program 上传attribute,uniform的数据。
3. glkViewControllerUpdate:(GLKViewController *)controller
Called before each frame is displayed, 所以此处所做的事情主要是根据传感器数据计算出绘制所需的参数,主要是变换矩阵,fov和viewport仅需要在更新视窗的时候更新。
调用 calculateFrameParametersWithHeadTransform... 函数,该函数主要功能:
- (VR模式下) 根据当前传感器数据计算出各变换矩阵,存入
leftEye和rightEye对象中去。 - (非VR模式下)
monocularEye更新viewport - (若需要时)更新左右眼的fov:
updateFovsWithLeftEyeFov:leftEye->fov() rightEyeFov:rightEye->fov()然后调用_distortionRenderer->fovDidChange(...)计算结果存储在传入的leftEyerightEye参数中。具体内容为:updateFovsWithLeftEyeFov...:计算出上下左右四个方向的fov角
fovDidChange(...): 根据fov值计算出两个眼的viewport具体数值。
_distortionRenderer->updateViewports(leftEye->viewport(), rightEye->viewport())更新左右眼的viewport
4. glkView:(GLKView *)view drawInRect:(CGRect)rect
绘制的回调函数。
_distortionRenderer->beforeDrawFrame()
- (需要时)
updateTextureAndDistortionMesh()(See [1]) glBindFramebuffer
drawFrameWithHeadTransform(...)回调:
[self.stereoRendererDelegate prepareNewFrameWithHeadViewMatrix:headTransform->headView()];
// ...
[self.stereoRendererDelegate drawEyeWithEye:_leftEyeWrapper];
// ...
[self.stereoRendererDelegate drawEyeWithEye:_rightEyeWrapper];
Rebind original framebuffer
_distortionRenderer->afterDrawFrame()--->undistortTexture(_textureID)(See [2])
5)finishFrameWithViewPort: callback: stereoRendererDelegate finishFrameWithViewportRect:
需要分析说明的如下
[1] DistortionRenderer::updateTextureAndDistortionMesh() :
- create mesh
- setup rendertexture and renderbuffer
首先创建两个program用于绘制畸变校正。这两个program的区别在于纹理,无矫正只有一个纹理sampler,带矫正的分别有RGB三个纹理sampler. 然后计算畸变矫正所需参数然后创建 DistortionMesh 对象: 创建对象时生成所需的vertexData和indexData 并绑定到相应的array buffer上面去。 再之后创建纹理、renderbuffer和framebuffer.这里创建的就是用于off-screen render的framebuffer,所以这里创建的纹理,其内容是空的,glTexImage2D(GL_TEXTURE_2D, 0, textureFormat, width, height, 0, textureFormat, textureType, nil); 因为这个SDK的功能就是留出这么一块framebuffer来给调用者绘制,绘制完了以后他自己将其当作纹理经过矫正后分别绘制到两个眼睛上面去。
[2] undistortTexture(_textureID) :
做一OpenGL状态的备份:将所有的OpenGL状态相关信息统统保存下来。若需要时,仍然是调用一遍 updateTextureAndDistortionMesh. 调用 renderDistortionMesh(_leftEyeDistortionMesh, textureID) 内部实现:目前已知vertexData indexData以及TextureId 将这些数据统统上传至畸变矫正用的program上,并绘制。完成后将保存的gl信息统统设置回去。
简单使用
分析提供的例子可知,简单使用时只需要继承这个CBDViewController类,并实现几个GLKViewController的方法,设置好stereoRendererDelegate 即可。主要的工作就是stereoRendererDelegate完成的,回调函数一览:
@protocol CBDStereoRendererDelegate <NSObject>
- (void)setupRendererWithView:(GLKView *)glView;
- (void)shutdownRendererWithView:(GLKView *)glView;
- (void)renderViewDidChangeSize:(CGSize)size;
- (void)prepareNewFrameWithHeadViewMatrix:(GLKMatrix4)headViewMatrix;
- (void)drawEyeWithEye:(CBDEye *)eye;
- (void)finishFrameWithViewportRect:(CGRect)viewPort;
@optional
- (void)triggerPressed;
@end
最后
我fork樂这个工程,做了一点点自己的修改,欢迎围观:
地址
CardboardSDK-iOS 源码简单分析的更多相关文章
- FFmpeg的HEVC解码器源码简单分析:解析器(Parser)部分
===================================================== HEVC源码分析文章列表: [解码 -libavcodec HEVC 解码器] FFmpeg ...
- FFmpeg源码简单分析:libswscale的sws_scale()
===================================================== FFmpeg的库函数源码分析文章列表: [架构图] FFmpeg源码结构图 - 解码 FFm ...
- Django-session中间件源码简单分析
Django-session中间件源码简单分析 settings里有关中间件的配置 MIDDLEWARE = [ 'django.middleware.security.SecurityMiddlew ...
- FFmpeg源码简单分析:结构体成员管理系统-AVOption
===================================================== FFmpeg的库函数源码分析文章列表: [架构图] FFmpeg源码结构图 - 解码 FFm ...
- negroni-gzip源码简单分析解读
negroni-gzip源码简单分析解读 这是一个为Negroni设计的gzip压缩处理中间件,需要用到已有的compress中的gzip,阅读了不长的源码之后,总结了一些关键要点和注意点. 检查是否 ...
- FFmpeg的HEVC解码器源码简单分析:概述
===================================================== HEVC源码分析文章列表: [解码 -libavcodec HEVC 解码器] FFmpeg ...
- FFmpeg的HEVC解码器源码简单分析:解码器主干部分
===================================================== HEVC源码分析文章列表: [解码 -libavcodec HEVC 解码器] FFmpeg ...
- urllib源码简单分析
对下面这段代码做分析 import urllib params = urllib.urlencode({'wd': 'python'}) f = urllib.urlopen("http:/ ...
- MongoDB 默认写入关注保存数据丢失问题与源码简单分析
MongoDB 默认写入关注可能保存数据丢失问题分析 问题描述: EDI服务进行优化,将原有MQ发送成功并且DB写入成功,两个条件都达成,响应接收订单数据成功,修改为只有有一个条件成功就响应接收数据成 ...
随机推荐
- keystone policy.json 的学习总结
keystone的policy.json文件位于:/etc/keystone/policy.json 其内容如下: 1 { 2 "admin_required": "ro ...
- UIView Methods
UIView翻译 (参考) 2011年04月12日 星期二 10:09 转载于:http://blog.csdn.net/tracylife/archive/2010/08/27/5842723.as ...
- phpcms v9 后台首页 去掉团队信息等版权
phpcms\languages\zh-cn\admin.lang.php $LANG['main_product_team'] = 'PHPCMS开发团队'; phpcms\modules\admi ...
- RSA实践指南
创建时间:2005-03-02 文章属性:原创 文章提交:watercloud (watercloud_at_xfocus.org) RSA算法基础->实践 讲讲自己学习RSA中的实践过程,已经 ...
- ucos事件邮箱信号量队列详解
Ucos的事件分为时钟,信号量,互斥性信号量,消息队列,以及消息邮箱 首先说信号量 信号量在ucos中的类型定义为OS_EVENT_TYPE_SEM,在任务控制块ecb中,主要是用到的是信号量计数器O ...
- Java虚拟机——进度1
Java 虚拟机 一.Java虚拟机的基本结构 ①类加载子系统:从文件系统或者网络中加载Class信息,存放在方法区中. ②方法区中存放放进来的Class信息,也包括一些运行时常量池信息包 ...
- 【Xilinx-Petalinux学习】-00-开始
基于自己的ZYNQ板子,在上面运行petalinux,已经搞得稳定了,之后详细记录. 现在功能:QSPI启动u-boot和kernel,vdma.tpg.osd.vtc等IP模块在Linux下的驱动, ...
- python 模块添加
python包含子目录中的模块方法比较简单,关键是能够在sys.path里面找到通向模块文件的路径.下面将具体介绍几种常用情况: (1)主程序与模块程序在同一目录下: 如下面程序结构:`-- src ...
- sqlite3命令行
1.查看版本信息 sqlite3 -verion 2.创建/打开数据库 sqlite3 数据库名 例:sqlite3 test.db 如果test.db不存在就创建 如果存在,则打开3.退出 .q/. ...
- Spark中的键值对操作
1.PairRDD介绍 Spark为包含键值对类型的RDD提供了一些专有的操作.这些RDD被称为PairRDD.PairRDD提供了并行操作各个键或跨节点重新进行数据分组的操作接口.例如,Pa ...