VR的原理和实现

一、     VR内容制作

VR内容场景的呈现分为两种情况:实景拍摄与3D建模场景制作。其中,3d建模场景制作又包含了“可以在VR里行走”和“不能在VR里行走”两种情况。

1.1全景拍摄的流程

第一步 拿到制作需求后,设计师进行头脑风暴思考场景内容,场景切换路径,界面里的文案交互逻辑,输出策划文档。

第二步 摄制团队在实景进行视频或全景拍摄,输出全景视频或全景图。

第三步 设计师进行视频剪辑或全景图拼接,及后期处理输出全景视频或全景图。

第四步 设计师制作交互动画及VR里的2d界面输出交互动画png序列,2d界面元素切图。

第五步 程序员写代码实现交互逻辑输出可交互的VR内容。

第六步 程序员设计师进入VR场景进行逻辑测试并不断完善内容。

1.2 3D建模场景制作的流程

第一步 设计师进行头脑风暴思考场景内容,场景切换路径,界面里的文案交互逻辑,输出策划文档。

第二步 设计师用草图或草模表现场景输出场景示意。

第三步 3d模型师根据场景示意图进行建模输出3d模型。

后面几步同1.1

 

全景拍摄需要用到全景摄像头到实地进行拍摄,3D建模则一般使用unity3D,UE等软件进行3D建模来构建虚拟场景,并在虚拟场景中设置全景镜头

 

1.3 全景素材的后期处理

不管是拍摄或者建模,得到的图片是分离的,比如6张照片or 12张照片等,这些照片涵盖了一个场景中的所有内容。

后期处理的第一步就是使用全景合成软件,对这些分离的素材进行合成,使之成为一张360度的全景图片

合成在网上有许多现成的软件,比如Kolor Autopano Video Pro,kolor autopano
giga,这两个软件就可以完成素材的合成以及拼接剪辑,制成一个VR的360全景视频

具体步骤可以参考:

http://www.vmovier.com/48630?from=post_hotcomment
<http://www.vmovier.com/48630?from=post_hotcomment>

1.4 VR播放器的简单原理

上述简单说明了一个VR视频是如何制作的,但是一个VR视频如果不使用特殊的播放器,那么播放出来的效果看上去是一个拉伸的长条形图片拼成的视频。


之所以Vr视频能让人有身处其中的感觉,是因为观看时人的视角处于VR视频空间中,而不是看到一个二维平面,因此就需要将本身的全景二维图,投影到一个立体的空间——立方体or球形。

简单球面纹理映射讲解

实现球面纹理映射有两种方法,一种是使用顶点的法向量来生成纹理坐标,另一个是使用顶点的位置向量来生成纹理坐标。

想象一个球体,球面上每一个点的法向量,可以是从球心起到该点的线段距离。球上每一点都可以视作一个无限小的平面。

Ps:法向量——垂直于平面的向量,叫做该平面的法向量

 

问题的本质是根据球面上每个点的法向量坐标生成对应的纹理坐标,请看下图,下图中外部的方框表示二维纹理坐标,其范围是(u,v)min = (0,0),
(u,v)max = (1,1),中间的圆形表示球面法向量坐标,其x,y分量的范围是(x,y)min = (-1,-1), (x,y)max = (1,1)。

 

所以问题的本质变成了两组坐标的映射,也即将区间(x,y)min - (x,y)max映射到区间(u,v)min -
(u,v)max。这里我们使用反正弦函数y = acrsin(x)来实现。先看一下它的函数图象。



由这个图象知,它的定义域x = (-1,1),值域是y = (-pi / 2, pi / 2)。我们稍作变型,得到下面两个公式。正好完成了由(-1,
1)到(0, 1)的映射。这里tu表示纹理的x坐标,tv表示纹理的y坐标,Nx表示顶点法向量的x轴分量,Ny表示顶点法向量的y轴分量。

tu = arcsin(Nx) / PI + 0.5
tv = arcsin(Ny) / PI + 0.5

二、     VR app实现研究

2.1 VR开源播放器

在网上找到了一个完整的PC上的VR开源播放器——VRPlayer 代码为VS工程,使用C#实现,支持windows平台。源码链接如下:

http://vrplayer.codeplex.com/SourceControl/latest
<http://vrplayer.codeplex.com/SourceControl/latest>

另外一套开源VR,就是google的 vr sdk。包括它的cardboard daydream,覆盖平台Android、IOS、以及Web。

覆盖安卓和IOS的实现是cardboard和daydream,Web的实现则是VR View。

安卓sdk使用java NDK部分为C++,VR view的实现目测是js。

Google vr有一个主页,链接如下:

https://developers.google.com/vr/ <https://developers.google.com/vr/>

 

2.2 google cardboard demo源码研究

在google vr sdk for android中 有一个cardboard 的sample——treasurehunt。

这是一个小游戏,玩家通过寻找空间中的立方体并吃掉它来进行游戏。

 

 

水平所限,只能简单的说下看懂的部分

跳过前面的头文件和全局变量声明,函数定义从91行开始,持续100行左右,应该是功能函数的一些定义,包括

矩阵乘法MatrixMul、

矩阵变幻到openGL数组 MatrixToGLArray、

矩阵元素乘法 MatrixVectorMul

其中这个函数PerspectiveMatrixFromView line 135

看函数名字似乎是将视图变为一个凸透镜的视图。在后续的一个DrawEye函数中有调用。

ModulateRect 看参数应该是创建一个符合宽和高的立方体模型,就是被玩家吃的那个立方体

CalculatePixelSpaceRect 看函数名是和像素什么的有关。。计算空间立方体的像素啥的吧,个人认为和VR生成关系不大

CheckGLError openGL报错检查函数

 

 

接下来是一个类定义TreasureHuntRenderer 看名称是该游戏的渲染作用的类

 

忽略其中的声音部分

简单的功能和判断函数如下:

OnTriggerEvent 触发事件,玩家视线看到立方体后,立方体着色 ,然后消失。

DrawCube 玩家视线看到立方体后,立方体着色

IsLookingAtObject 判断玩家视线是否算是看到立方体

OnPause 暂停游戏

OnResume 取消暂停游戏

HideObject 使立方体消失

一系列draw函数应该是比较关键的部分

drawFrame->drawEye->drawFloor,drawCube

这一块代码就看的不是很明白,关键的VR映射部分应该就是这里实现的

 

DrawFrame中

 

这里获取头部姿势,然后通过头部的姿势获取眼睛的一个目视范围吧?

接下来DrawEye

 

根据上个函数中的参数left_eye_view_matrix/right,视野范围4*4矩阵,确定灯光的范围和能看到的地板的范围吧,并把地板也着色。

 

InitializeGl初始化各种颜色,位置参数

 

其实能形成VR效果的关键应该就是在这些draw函数的参数上。应该是通过一些公式,将图像映射成了玩家眼中的立体空间。

关键的参数变量数据结构定义:

 

第一个应该是数据的值域范围矩阵,第二个则是对象的空间参数,xyz向量以及一个w标量。

OpenGL知识补充:

通常我们使用 4 维向量 (x, y, z, w) 表示在3D空间中的一个点,最后一维 w
表示齐次坐标。齐次坐标的含义是两条平行线在投影平面的无穷远处相交于一点,但在 Matrix 中没有表示无穷大,所以增加了齐次坐标这一维。

3D空间的物体投影到2D平面上时,就需要使用到齐次坐标,因此我们需要使用 4 × 4 的 Matrix 来表示变换。在编程语言中,这样的 Matrix
可用大小为 16 的一维数组或4 × 4 的二维数组来表示。由于矩阵乘法不满足乘法交换律,用数组表示 Matrix
又分为两种形式:行主序和列主序,它们在本质上是等价的,只不过是一个是右乘(行主序,矩阵放右边)和一个是左乘(列主序,矩阵放左边)。OpenGL
使用列主序矩阵,即列矩阵,因此我们总是倒过来算的(左乘矩阵,变换效果是按从右向左的顺序进行): 投影矩阵 × 视图矩阵 × 模型矩阵 × 3D位置。

后来找到的上面矩阵变幻和数据结构定义的原理:

http://blog.csdn.net/lyx2007825/article/details/8792475
<http://blog.csdn.net/lyx2007825/article/details/8792475>

http://blog.csdn.net/kesalin/article/details/7168967
<http://blog.csdn.net/kesalin/article/details/7168967>




转载自:https://blog.csdn.net/jmz19910110/article/details/52440299

友情链接
KaDraw流程图
API参考文档
OK工具箱
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:ixiaoyang8@qq.com
QQ群:637538335
关注微信