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写入成功,两个条件都达成,响应接收订单数据成功,修改为只有有一个条件成功就响应接收数据成 ...
随机推荐
- Quick Cocos2dx 初步战斗
呵呵,图片先来一发: 最近懒,很懒,连我自己都觉得有点可耻了. 但是实在没有什么东西啊,温水煮青蛙的什么的. 吐槽完成,以上. 目前完成了简单的战斗部分,AI还需要抽出来. 然后突然之间想到手游的帧频 ...
- CentOS 6.4 x64 安装 配置 Redmine 2.4.1
Redmine 安装配置 1. 安装Redmine 所需的依赖 首先安装 yaml wget http://pyyaml.org/download/libyaml/yaml-0.1.4.tar.gz ...
- [FTP]xferlog日志解析
[root@teacher ~]# cat /var/log/xferlogMon Jan 25 20:41:39 2016 1 10.0.222.156 913268 /sys/sys64/Pack ...
- (简单) POJ 3259 Wormholes,SPFA判断负环。
Description While exploring his many farms, Farmer John has discovered a number of amazing wormholes ...
- nginx实战
原文:http://www.cnblogs.com/yucongblog/p/6289628.html nginx实战 (一) nginx环境的搭建安装流程: 1 通过ftp将nginx-1.11 ...
- 分析$.isPlainObject
作者:zccst 本次学习$.isPlainObject,是不是一个普通对象.测试对象是否是纯粹的对象(通过 "{}" 或者 "new Object" 创建的) ...
- 关于IP网段间互访的问题—路由是根本(转)
源: 关于IP网段间互访的问题—路由是根本
- php小知识。
合并数组的2个方式区别 1)键名为数字时,array_merge()不会覆盖掉原来的值,但+合并数组则会把最先出现的值作为最终结果返回,而把后面的数组拥有相同键名的那些值“抛弃”掉(不是覆盖) 2)键 ...
- Test 17
BZ OI 队测 T1: 题目大意: 喵星系有n个星球,标号为1到n,星球以及星球间的航线形成一棵树. 所有星球间的双向航线的长度都为1.小昕要在若干个星球建矿石仓库,设立每个仓库的费用为K.对于未设 ...
- sql语句:if exists语句使用
') begin print('exists ') end else begin print('no exists ') end go