1. 程式人生 > >Google VR 開發淺析

Google VR 開發淺析

VR 是什麼

VR Virtual Reality 虛擬現實

VR平臺

CardBoard
世界上最流行和最易用的手機VR平臺

DayDream
一個新的手機VR平臺,低時延、更逼真、易互動。

Google VR SDK

VR SDK同時支援DayDream和CardBoard。
包含了一些用於建立App的簡單API和支援DayDream手機、DayDream控制器的複雜API。

Google VR SDK 涵蓋了Android、IOS、Unity三大平臺

示例

開發者可以下載上述連線中的程式碼,並執行其中的示例程式。
這些示例程式使用VR SDK中的幾大特性:

  1. Binocular rendering (雙目渲染)
    在VR中為每個眼睛展示的分屏檢視
  2. Spatial audio (空間聲音)
    聽起來像來自VR世界的特殊空間的聲音
  3. Head movement tracking (頭部移動跟蹤)
    當頭部移動時,VR世界畫面會時時更新
  4. Trigger input (觸發輸入)
    在VR世界,使用者可以通過點選按鈕來做一些操作

VR View

VR View允許開發者在網站或app中嵌入360度全景多媒體檔案(圖片和視訊)。這個技術主要是提供給傳統的開發者,可以通過在app中新增動態內容來提升使用者體驗。比如旅行或房地產型別的app,可以讓使用者足不出戶就體驗到虛擬場景。

VR View同時支援web和Native app。

WebModern versions of Chrome on Windows, OSX, Linux, Android, and iOS.
Modern versions of Safari on OSX and iOS. Modern versions of Firefox
on Windows, OSX, and Linux. Modern versions of IE 11 and Edge on
Windows. Native

iOS 8 and higher. Android 4.4 (Kit Kat) and higher.

VR View同時支援單聲道和立體聲的圖片和視訊,但是圖片和視訊的儲存格式必須為equirectangular-panoramic格式,這是一種常見的攝像頭尺寸支援的格式。

圖片規格:

  • 支援jpeg、png、gif。為了提高壓縮,建議使用jpeg格式。
  • 為了最大化相容和效能,圖片尺寸應控制在兩種內(2048或4096)
  • 單聲道圖片應當是2:1比例(例:4096x2048)
  • 立體聲圖片應當是1:1比例(例:4096x4096)

視訊規格:

  • VR view視訊應當儲存為MP4格式,並使用H.264編碼
  • 單聲道視訊應當為2:1比例
  • 立體聲視訊應當是1:1比例
  • 一些舊裝置不支援解碼超過1080p(1920x1080)的視訊。如果最大化適配行和質量是首要的,建議使用者同時提供單聲道1920x1080視訊和立體聲2048x2048視訊或者更高

VR view是客戶端的顯示技術,那麼我們怎麼去拍攝符合VR view要求的內容呢?

  1. 真實世界中的拍攝
    有兩個工具:

Ricoh Theta 一個非常流行的,相對廉價的用來拍攝單聲道相片和視訊的裝置。

  1. CG 拍攝
    VR view的圖片不僅僅限制在真實世界中拍攝。CGI(計算機合成影象)可以為所有的東西生成360度全景照片和視訊,最流行拍攝解決方案如下:

下面用虛擬碼展示如何用VrPanoramaView和VrVideoView展示360度圖片和視訊。

佈局程式碼

<com.google.vr.sdk.widgets.pano.VrPanoramaView
            android:id="@+id/pano_view"
            android:layout_margin="5dip"
            android:layout_width="match_parent"
            android:scrollbars="@null"
            android:layout_height="250dip"/>

<com.google.vr.sdk.widgets.video.VrVideoView
          android:id="@+id/video_view"
          android:layout_width="match_parent"
          android:scrollbars="@null"
          android:layout_height="250dip"/>

Java程式碼

//展示全景圖片
 panoWidgetView = (VrPanoramaView) findViewById(R.id.pano_view);
//圖片載入結果回撥
private class ActivityEventListener extends VrPanoramaEventListener {
    /**
     * Called by pano widget on the UI thread when it's done loading the image.
     */
    @Override
    public void onLoadSuccess() {
      loadImageSuccessful = true;
    }

    /**
     * Called by pano widget on the UI thread on any asynchronous error.
     */
    @Override
    public void onLoadError(String errorMessage) {
      loadImageSuccessful = false;
      Toast.makeText(
          SimpleVrPanoramaActivity.this, "Error loading pano: " + errorMessage, Toast.LENGTH_LONG)
          .show();
      Log.e(TAG, "Error loading pano: " + errorMessage);
    }
  }
//設定圖片載入監聽
    panoWidgetView.setEventListener(new ActivityEventListener());

//載入影象的Bitmap資料 istr是一個檔案輸入流
//VrPanoramaView.Options是用來配置圖片格式的
// TYPE_MONO 包含單一圓柱的全景影象
// TYPE_STEREO_OVER_UNDER 影象包含了兩個大小相等、垂直相交的圓柱全景影象。上圖展示給左眼,下圖展示給右眼。
panoWidgetView.loadImageFromBitmap(BitmapFactory.decodeStream(istr), panoOptions);


//展示全景視訊
videoWidgetView = (VrVideoView) findViewById(R.id.video_view);
    videoWidgetView.setEventListener(new ActivityEventListener());
//VrVideoEventListener同時對視訊載入和操作的回撥
private class ActivityEventListener extends VrVideoEventListener  {
    /**
     * Called by video widget on the UI thread when it's done loading the video.
     */
    @Override
    public void onLoadSuccess() {
      Log.i(TAG, "Sucessfully loaded video " + videoWidgetView.getDuration());
      loadVideoStatus = LOAD_VIDEO_STATUS_SUCCESS;
      seekBar.setMax((int) videoWidgetView.getDuration());
      updateStatusText();
    }

    /**
     * Called by video widget on the UI thread on any asynchronous error.
     */
    @Override
    public void onLoadError(String errorMessage) {
      // An error here is normally due to being unable to decode the video format.
      loadVideoStatus = LOAD_VIDEO_STATUS_ERROR;
      Toast.makeText(
          SimpleVrVideoActivity.this, "Error loading video: " + errorMessage, Toast.LENGTH_LONG)
          .show();
      Log.e(TAG, "Error loading video: " + errorMessage);
    }

    @Override
    public void onClick() {
      togglePause();
    }

    /**
     * Update the UI every frame.
     */
    @Override
    public void onNewFrame() {
      updateStatusText();
      seekBar.setProgress((int) videoWidgetView.getCurrentPosition());
    }

    /**
     * Make the video play in a loop. This method could also be used to move to the next video in
     * a playlist.
     */
    @Override
    public void onCompletion() {
      videoWidgetView.seekTo(0);
    }
  }
//支援兩種載入方式,從asset資料夾中或從一個uri中讀取視訊資料
//VrVideoView.Options同樣是用來配置視訊格式的
videoWidgetView.loadVideoFromAsset("congo.mp4", options);
或
videoWidgetView.loadVideo(fileInformation[0].first, fileInformation[0].second)

除此外還有一些控制渲染、播放的方法:
videoWidgetView.pauseRendering();
videoWidgetView.resumeRendering();
videoWidgetView.shutdown();
videoWidgetView.playVideo();
videoWidgetView.pauseVideo();

shutdown()一定要在onDestroy()時呼叫,用來釋放佔用記憶體。

Spatial Audio 空間聲音

Google VR SDK一個重要的特性就是一個為手機VR高度優化的一流的音訊渲染引擎,給聽眾更真實的空間聲音體驗。