CardboardSDK-iOS 源碼簡單分析

該項目地址: 地址
克隆地址爲 https://github.com/rsanchezsaez/CardboardSDK-iOS.gitgit

目前若是想在iOS設備上實現雙目VR的功能,Google 已經提供了官方的sdk,上手簡單,可是因爲在實際使用中有其餘需求,GVR的源碼沒法修改,因此仍是使用這個野生的SDK來開發。這篇文章主要就是簡單分析一下這個sdk的ViewController 的代碼,至於內部的複雜數學計算,暫時沒法涉及。github

CBDViewController

主要要分析的就是 CBDViewController 這個類,其繼承了 GLKViewController 並實現樂 GLKViewControllerDelegate 這個接口。成員:stereoRendererDelegate 負責實現若干個回調函數,好比在Cardboard各個設置完成後進行所需的繪製工做。app

1. Init

初始化各個成員變量,設置GLKViewController的delegate爲self,啓動設備的傳感器,開始監聽。函數

2. ViewDidLoad

建立OpenGL的Context 並回調 [self.stereoRendererDelegate setupRendererWithView:self.view] 此時設置Context爲 glview.context,能夠進行繪製的準備工做,好比建立program 上傳attribute,uniform的數據。code

3. glkViewControllerUpdate:(GLKViewController *)controller

Called before each frame is displayed, 因此此處所作的事情主要是根據傳感器數據計算出繪製所需的參數,主要是變換矩陣,fov和viewport僅須要在更新視窗的時候更新。orm

調用 calculateFrameParametersWithHeadTransform... 函數,該函數主要功能:對象

  1. (VR模式下) 根據當前傳感器數據計算出各變換矩陣,存入leftEyerightEye對象中去。
  2. (非VR模式下)monocularEye 更新viewport
  3. (若須要時)更新左右眼的fov:updateFovsWithLeftEyeFov:leftEye->fov() rightEyeFov:rightEye->fov() 而後調用 _distortionRenderer->fovDidChange(...) 計算結果存儲在傳入的 leftEye rightEye 參數中。具體內容爲:
    • 1) updateFovsWithLeftEyeFov...:計算出上下左右四個方向的fov角
    • 2) 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

2) drawFrameWithHeadTransform(...) 回調:接口

[self.stereoRendererDelegate prepareNewFrameWithHeadViewMatrix:headTransform->headView()];
// ...
[self.stereoRendererDelegate drawEyeWithEye:_leftEyeWrapper];
// ...
[self.stereoRendererDelegate drawEyeWithEye:_rightEyeWrapper];

3) Rebind original framebuffer開發

4) _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樂這個工程,作了一點點本身的修改,歡迎圍觀:
地址

相關文章
相關標籤/搜索