【Oculus SDK】星空 VR

星空 VR

介紹

想做一個,類似於造物主的遊戲(所以英文叫demiurge)。玩家能夠往這個地方扔星球。本來希望有好一點的交互碰撞效果結果後來懶了(……)所以最後做出來不太像遊戲了233也是很慘的。

不能看的話B站視頻連接https://www.bilibili.com/video/av31583253

代碼鏈接
https://github.com/Birdy-C/Demiurge

實現

環境配置

一開始在選擇配置的時候考慮的一個是Oculus提供的官方SDK,另一個就是基於SteamVR的OpenVR SDK

適當權衡之後,選擇了Oculus官方提供的SDK。因爲看起來文檔相對詳細而且排版比較清楚,有比較具體的例程。

當然Oculus官網全程需要翻牆……這一點確實非常的不友好。客戶端大概下載了五六個小時,後面用戶登錄又折騰了蠻久。確實對於國內開發者不太友好。

此外,Oculus有一系列的Unity的中文教程,但是基本上沒有PC SDK的中文資料料。整個過程的主要參考是官網文檔和官網提供的教程。

模型建立

我採用對球分段的方式,用四邊形(三角面片)去逼近球。

生成球的函數,傳入參數是球的中心、球的半徑、theta方向上的分段數和phi方向上的分段數。theta和phi的值和座標的對應關係爲:

result=center+(cos(ϕ)cos(θ),sin(ϕ),cos(ϕ)sin(θ))radius

在theta和phi分段都爲5的時候,能夠清楚的看到扭曲的輪廓

這裏寫圖片描述

這個數值設置爲20之後,就能感覺到這是一個非常完整的球。

這裏寫圖片描述

由於這裏沒有陰影所以表現效果會差一點orz

LOD

因爲在這個場景中,球是用三角面片去逼近的,所以一旦球在近處,失真會非常的明顯。

所以這裏決定做一下離散的LOD。離散的相對實現比較容易。實現的時候,預先存儲多個模型,可以直接根據之前到相機的位置以及球的半徑確定採用哪個模型。

因爲半徑在屏幕上決定了三角面片的邊的長度,所以取

k=distanceradius

由k的取值,來確定模型的精度。

當然也遇到了離散模型所可能會遇到的突變的問題。
下圖是在測試場景中,極小的位移中LOD變化(最後實現的時候對數值做了一定的調整所以不會那麼明顯)。

這裏寫圖片描述
這裏寫圖片描述

相機

VR遊戲中的相機,和常規的3D遊戲不同之處在於需要單獨確定兩個相機的位置。根據玩家左眼和右眼的位置,單獨確定左眼和右眼看到的物體,分別渲染。
但是這一步相對比較常規,在例程中提供了左右眼單獨渲染以及提供可視化窗口的操作。

此外在具體實現的時候,對於一些特殊物體,比如天空盒和UI,這種位置會跟隨玩家的位置變化的物體(但是旋轉不會)。這就需要我們操作觀察矩陣。需要將光差矩陣移除位移部分但是保留矩陣的旋轉部分。

glm::mat4 view = glm::mat4(glm::mat3(camera.GetViewMatrix()));

我們通過取4x4矩陣左上角的3x3矩陣來移除變換矩陣的位移部分。我們可以將觀察矩陣轉換爲3x3矩陣(移除位移),再將其轉換回4x4矩陣,來達到類似的效果。

紋理生成及映射

紋理生成

紋理主要採用的是perlin噪聲。perlin噪聲是一種經典的自然噪聲生成算法。
我們給圖像賦予一個底色,然後利用噪聲的性質,我們使用2D和1D的perlin噪聲,分別生成不同的圖。

1D的perlin噪聲:
perlin1

2D的perlin噪聲:
perlin2

用戶可以通過界面選擇分段、顏色、以及選擇不同的隨機數來生成不同的紋理。
隨機數的設置,主要是基於perlin噪聲本身三維的特性,對於確定好的xy設定不同的z能夠得到不同的值。

perlin噪聲用到是stb庫。這個庫同時也用於這個項目中的圖像讀寫。

紋理映射

由於之前在生成紋理的時候,通過下述公式

result=center+(cos(ϕ)cos(θ),sin(ϕ),cos(ϕ)sin(θ))radius

已經把球上的點和theta和phi對應起來。只需要簡單的把theta和phi映射到[0,1]區間內,就可以實現紋理的映射。

我們分別對已有的紋理以及我們生成的紋理進行了測試,映射結果如下:

earth
地球的映射紋理

sun
太陽的映射紋理

perlin1 texture
1D perlin噪聲

perlin2 texture
2D Perlin噪聲

交互設計

交互界面

在設計界面的形式的時候,嘗試過多種形式。

第一種是在視線的右上方之類的懸浮一個對話框,這樣用戶可選擇。
第二種是固定在相對用戶的某個特定位置上,類似於天空盒。穩定的位於用戶某個特定方向的特定距離上。
第三種是位於某個固定位置上,但是條件轉向使得其始終面向用戶。

主流的VR遊戲中這三種都有用到。在嘗試的時候覺得第一種相對會讓用戶感覺不真實,所以在這個過程中使用了後面兩種方法。

在該界面是長期需要使用的時候,採用第二種形式。比如幫助界面和星球設置的界面。
UI
這個界面一直位於用戶的一側。

在有非常明確的對應關係,比如顯示星球的速度的時候,採用第三種方式。
UI1
這個速度條一直位於星球的下方,會隨着用戶運動轉向保證正對用戶。

此外這裏的感受就是,一定不要拿着個頭盔直接通過屏幕的輸出來判斷是否合適。一定要自己戴上頭盔去試一試,這樣才能知道是不是真的合適。有的時候在屏幕上看感覺大小蠻合理的,但是戴上頭盔之後發現這個UI鋪天蓋地我還得轉頭才能看清楚整個UI界面。

這裏還有遇到的一個問題,我用的是stb庫做的圖像讀寫,但是到文字輸出那一塊發現找不到對應的頭文件。考慮用SDL庫做輸出,但是後期轉到這裏成本也比較高就放棄了……所以最後看到的文字都是用圖像的形式預先計算的。

GUI雖然難度不大,但是計算和設計非常的麻煩,需要一些複雜的定位以及和美工的不斷協調。

手柄事件

我們在設計的時候,決定左手確定用戶的移動,右手確定交互和響應。

Oculus Touch手柄如下

左手上方的撥盤決定用戶的前進/後退移動。

右手撥盤來調整用戶的選擇,左右打開下一級目錄,上下選擇這一級目錄的不同內容,最後通過AB按鍵來調整現在選中目標的數值。
我們的右手手柄的響應分爲兩段。用右手手柄操作星球設置的時候,爲了避免在一次按鍵的過程中撥盤的多次響應(因爲它主要作用可能不是這樣的選擇),設置一定的時間響應一次,這樣可以避免選中區域瘋狂跳動。而在用手柄設置星球的位置和速度的時候,連續的響應能給用戶更好的體驗。

左手只有相對簡單的移動事件。

仿真

運動

用戶可以在交互界面上自己定義自轉速度和星球的體積,這之後星球會按照預定好的信息自傳。

接下來用戶可以設定星球到主天體(這個宇宙的中心,類似於太陽對太陽系的概念)的距離以及星球的初始速度。

然後會按照

a=kdistance

的基本公式計算該星球繞主天體運動的軌道。在每次計算的時候不斷根據加速度更新速度,再根據速度更新位置。得到的結果會是一個比較接近真實情況的橢圓。

測試的時候單個星球的結果如下:

這裏寫圖片描述
這裏寫圖片描述
這裏寫圖片描述

後面

說來蠻慚愧的,畢竟這個專業圖形學相關的課程非常的多,但這卻是我第一次用可編程管線寫的項目。果不其然被shader弄的很狼狽,因爲完全沒有經驗根本無從知道到底是哪一個部分出現了疏忽。再加上我選擇從例程入手,這樣一方面確實減少了學習Oculus SDK相關的工作量,卻也被這份可擴展性較差的代碼弄得非常頭大。

感覺選擇用OpenGL從底層寫起,初期確實壓力比較大,而且最後實現效果受到各方面的約束,我們必須純靠代碼來實現每個功能,但是個人覺得這是一次不錯的嘗試。

當然也有很多的不足。我覺得我們這個設置一個架空的宇宙爲背景有一定的取巧,因爲我衡量自己現有的能力還不足以寫出真實感相對較強的VR項目。

不足及改進

感覺最後還有很多欠缺的地方。這部分的欠缺主要原因是經驗不足。

Shader

Shader的問題很多。最後實現的時候我們幾乎沒有調整已有的shader,所以也就沒有實現更加具體效果,比如陰影、光照貼圖等種種;而且計算效率相對較低,如果能夠熟悉shader的語法的話很多CPU的運算可以轉移到GPU當中,這樣肯定會提高渲染的效率。

這一部分主要的限制在於Oculus的例程提供的是GLSL1.50,而我之前所接觸的是3.30,調整的時候遇到蠻多問題。並且shader的顯示比較難,很難知道具體是哪一部分出現的問題。

此外還有原因是,例程的可拓展性較差,而我們的總的結構是參考例程的。如果下一次要寫這樣的程序,應該會考慮自己重新打整個程序的框架。

加速

我在寫之前估計,對於星球的物理運動可以和渲染顯示分成不同的線程。Oculus官方提供了計算幀率等等的文檔以及對於加速的一些建議。但是因爲這個項目的話幀率並不是主要的瓶頸,所以沒有很注意做這些方面。如果以後開發大型項目的話這確實是需要考慮的一點。I/O和內存分配都還有很大的進步空間。

參考資料

過程式紋理:https://www.gamasutra.com/view/feature/131507/a_realtime_procedural_universe_.php

紋理資源:https://www.solarsystemscope.com/textures/

球面映射:https://blog.csdn.net/t3swing/article/details/79006216

天空盒:https://learnopengl-cn.github.io/04%20Advanced%20OpenGL/06%20Cubemaps/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章