该项目地址: 地址

克隆地址为 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... 函数,该函数主要功能:

  1. (VR模式下) 根据当前传感器数据计算出各变换矩阵,存入leftEyerightEye对象中去。
  2. (非VR模式下)monocularEye 更新viewport
  3. (若需要时)更新左右眼的fov:updateFovsWithLeftEyeFov:leftEye->fov() rightEyeFov:rightEye->fov() 然后调用 _distortionRenderer->fovDidChange(...) 计算结果存储在传入的 leftEye rightEye 参数中。具体内容为:
      1. updateFovsWithLeftEyeFov...:计算出上下左右四个方向的fov角
      1. fovDidChange(...): 根据fov值计算出两个眼的viewport具体数值。
  4. _distortionRenderer->updateViewports(leftEye->viewport(), rightEye->viewport())更新左右眼的viewport

4. glkView:(GLKView *)view drawInRect:(CGRect)rect

绘制的回调函数。

  1. _distortionRenderer->beforeDrawFrame()
  • (需要时) updateTextureAndDistortionMesh() (See [1])
  • glBindFramebuffer
  1. drawFrameWithHeadTransform(...) 回调:
    [self.stereoRendererDelegate prepareNewFrameWithHeadViewMatrix:headTransform->headView()];
// ...
[self.stereoRendererDelegate drawEyeWithEye:_leftEyeWrapper];
// ...
[self.stereoRendererDelegate drawEyeWithEye:_rightEyeWrapper];
  1. Rebind original framebuffer

  2. _distortionRenderer->afterDrawFrame()---> undistortTexture(_textureID) (See [2])

5)finishFrameWithViewPort: callback: stereoRendererDelegate finishFrameWithViewportRect:

需要分析说明的如下

[1] DistortionRenderer::updateTextureAndDistortionMesh() :

  1. create mesh
  2. 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 源码简单分析的更多相关文章

  1. FFmpeg的HEVC解码器源码简单分析:解析器(Parser)部分

    ===================================================== HEVC源码分析文章列表: [解码 -libavcodec HEVC 解码器] FFmpeg ...

  2. FFmpeg源码简单分析:libswscale的sws_scale()

    ===================================================== FFmpeg的库函数源码分析文章列表: [架构图] FFmpeg源码结构图 - 解码 FFm ...

  3. Django-session中间件源码简单分析

    Django-session中间件源码简单分析 settings里有关中间件的配置 MIDDLEWARE = [ 'django.middleware.security.SecurityMiddlew ...

  4. FFmpeg源码简单分析:结构体成员管理系统-AVOption

    ===================================================== FFmpeg的库函数源码分析文章列表: [架构图] FFmpeg源码结构图 - 解码 FFm ...

  5. negroni-gzip源码简单分析解读

    negroni-gzip源码简单分析解读 这是一个为Negroni设计的gzip压缩处理中间件,需要用到已有的compress中的gzip,阅读了不长的源码之后,总结了一些关键要点和注意点. 检查是否 ...

  6. FFmpeg的HEVC解码器源码简单分析:概述

    ===================================================== HEVC源码分析文章列表: [解码 -libavcodec HEVC 解码器] FFmpeg ...

  7. FFmpeg的HEVC解码器源码简单分析:解码器主干部分

    ===================================================== HEVC源码分析文章列表: [解码 -libavcodec HEVC 解码器] FFmpeg ...

  8. urllib源码简单分析

    对下面这段代码做分析 import urllib params = urllib.urlencode({'wd': 'python'}) f = urllib.urlopen("http:/ ...

  9. MongoDB 默认写入关注保存数据丢失问题与源码简单分析

    MongoDB 默认写入关注可能保存数据丢失问题分析 问题描述: EDI服务进行优化,将原有MQ发送成功并且DB写入成功,两个条件都达成,响应接收订单数据成功,修改为只有有一个条件成功就响应接收数据成 ...

随机推荐

  1. 转发:招聘一个靠谱的 iOS

    觉得很瘦感触,因此转发:http://blog.sunnyxx.com/2015/07/04/ios-interview/ 近一年内陆续面试了不少人了,从面试者到面试官的转变让我对 iOS 招聘有了更 ...

  2. CodeForces 598E Chocolate Bar

    区间DP预处理. dp[i][j][k]表示大小为i*j的巧克力块,切出k块的最小代价. #include<cstdio> #include<cstring> #include ...

  3. 如何获取app的素材,做出一个高仿的app

    第一步:在iTunes中搜索你想要的app,然后点击下载: 下载完成之后右键点击:在Finder中显示 在finder中右键用"归档工具打开" 会显示如下内容: "显示包 ...

  4. [iOS、Unity、Android] 浅谈闭包的使用方法

    前言 我们经常所编程语言的的进步速度是落后于硬件的发展速度的. 但是最近几年,闭包语法在各个语言中都有自己的体现形式,例如 • C语言中使用函数指针作为回调函数的入口: • Java和C#语言中的La ...

  5. STM32 USB虚拟串口(转)

    源:STM32 USB虚拟串口 串口调试在项目中被使用越来越多,串口资源的紧缺也变的尤为突出.很多本本人群,更是深有体会,不准备一个USB转串口工具就没办法进行开发.本章节来简单概述STM32低端芯片 ...

  6. webstrom命令大全

    Ctrl + Space:Basic code completion (the name of any class, method or variable) 基本代码完成(任何类.函数或者变量名称), ...

  7. RDA5820收音机芯片驱动

    RDA5820 是北京锐迪科推出的一款集成度非常高的立体声 FM收发芯片.该芯片具有以下 特点:   FM 发射和接收一体   支持 65Mhz~115Mhz的全球 FM接收频段,收发天线共用. ...

  8. Exception和RuntimeException的区别

    Exception:在程序中必须使用try...catch进行处理. RuntimeException:可以不使用try...catch进行处理,但是如果有异常产生,则异常将由JVM进行处理.

  9. libusb开发者指南(转)

    源:libusb开发者指南 译者: gashero 作者: Johannes Erdfelt 日期: 2010-04-17 地址: http://libusb.sourceforge.net/doc/ ...

  10. IOS开发中Xcode常用插件安装与管理(转)

    XCode中插件管理工具:Alcatraz    转自http://www.cocoachina.com/industry/20140506/8325.html 苹果现在的成绩得益于其始终如一的坚持. ...