为什么需要全景视频?
我的大部分博客文章都是针对游戏开发人员的。如果您是其中之一,则可能想知道您可能对创建360°视频感兴趣。虚拟现实是一个非常成功的行业,每年都会在各种平台上发布更多游戏。许多玩家通过预告片了解VR游戏,不幸的是,这些预告片是以2D形式录制的。
如果您想更进一步,可以创建一个可选的全景预告片以展示游戏的全部潜力。尽管播放VR通常需要昂贵的耳机,但YouTube本身就支持全景视频,而无需其他硬件。而且,如果您有电话,可以使用Google Cardboard轻松将其变成VR耳机。
这可以为人们提供更加身临其境的体验,并使他们对游戏的意义有所了解。电影It(请参见下面的预告片)和The Conjuring等电影通过创建VR游戏(全景视频中的预告片)充分利用了这一点,以提供更互动的体验。
最后,全景视频非常适合用于教育目的,如《所有发现的系外行星:叙述的360 VR旅程》中所示。
处理全景视频
您很可能熟悉YouTube及其运作方式。但是,全景视频并不为许多人所熟悉。大多数视频记录在仅捕获一小部分环境的摄像机上。全景视频同时记录了各个方向上发生的一切。这通常需要称为全向摄像机的特殊摄像机。他们要么使用曲面镜将周围环境反射到传统相机中(就像鱼眼镜头一样),要么使多个相机朝向不同的方向。一个这样的相机就是GoPro Omni(请参阅下文),它实际上是一个包含六个标准鱼眼镜头的设备。
显而易见,为什么录制全景视频所需的设备通常比传统相机要贵。但是,这不是限制其分布的唯一原因。正确播放全景视频需要特殊的软件和硬件。屏幕像摄像机一样,仅设计用于重现环境的一小部分。通过允许观看者“旋转”视频以便他们环顾四周,YouTube得以解决了这一限制。如果您正在观看来自手机或平板电脑的全景视频,通常会在太空中移动它以360°角度观看“球体”的不同部分。
YouTube支持两种类型的全景视频:单声道和立体声(后者通常称为VR视频))。两者之间的区别在于,立体声视频专用于VR耳机,可以传达传统视频无法感受到的深度感。这不是通过一个视频而是两个视频,每个眼睛一个视频来实现的。这两个视频是由两个摄像机同时录制的,它们之间的距离可与两眼之间的距离相媲美。结果,就像在日常生活中一样,VR视频可以“欺骗”大脑以感知真正的距离。
下表显示了这两类视频的要求。
名称 | 360°视频 | 虚拟现实视频 |
单核细胞增多症 | 立体声 | |
2D | 3D | |
链接 | 支持 | 支持 |
帧频 | 24、25、30、48、50、60 | 25、30、50、60 |
格式 | 等距
纵横比2:1 |
上下等距
纵横比1:1 |
解析度 | 推荐:7168 x 3584,最大8192 x 4096 | 5120 x 5120至8192 x 8192 |
请注意,YouTube一直在努力改善对全景视频的支持,因此将来可能会有所改变。在遵循这些规范之前,请阅读表中的参考信息。
投影影片
全景视频的第一个棘手的部分是将球体编码为平坦的表面。这是必要的,因为尽管全向摄像机可以在所有方向上进行记录,但是仍然需要将每个帧转换为传统的平面图像。
有很多种方法改造(严格地说,项目)的球体上的矩形。也许最有名的是圆柱投影,自1569年制图师Gerard Mercator开始使用圆柱投影以来,圆柱投影就很流行,将行星表面转换成平面图。
但是,等角投影最常用于全景视频中(请参见下文)。
空间声音
全景视频(单声道和立体声)都可以支持空间音频。标准视频具有两个音频通道(左和右),用于在使用立体声耳机收听时产生方向感。空间音频使您可以编码声源的真实方向,而不仅仅是左右。这意味着使用正确的设备,您可以完全沉浸其中,并理解周围声音的方向。
尽管有VRVR视频的名称,但它不如“真实” VR游戏好,因为即使VR耳机可以跟踪头部的动作,视频也是从固定点渲染的。就像在VR游戏中一样,无法移动并看到物体背后的东西。这可能会有些混乱,尤其是在与环绕声结合使用时。当您长时间从事VR项目(游戏或视频)时,您可以习惯它。重要的是进行足够详细的游戏测试,以确保最终产品的便利性,并找出使玩家或观众感到不适的限制。
全景视频不需要空间音频。YouTube支持两种格式:
- 一阶Ambisonics
- 具有头锁立体声的一阶Ambisonics
Ambisonics是一种声音格式,不仅可以记录声音,还可以记录声音的来源。一阶Ambisonics(FOA)使用四个音频通道对声源方向性进行编码。为了大致了解这是如何工作的,我会说录制FOA声音有点像用四个麦克风录制。常见的误解是这四个麦克风位于主要位置(一个在观看者前面,另一个在后面,左侧第三个和右侧第四个)。这不是Ambisonics的工作方式,但是我们可以在其他文章中谈论它。
尽管FOA使用4个频道,但YouTube还支持6频道版本,该版本仅添加了传统的左右立体声频道。这种格式称为带头锁立体声的FOA...
应特别注意编码全景视频(立体声或单声道),因为并非所有格式都支持4或6个音频通道。YouTube建议以下内容:
- 格式:MP4,MOV
- 编解码器:H.264,ProRes,DNxHR
如果您使用的是Premiere Pro 2018或更高版本,则最好将视频编码为Quicktime ProRes编解码器。您可以在此处阅读有关YouTube支持的空间音频格式的更多信息。
如何在Unity中创建全景视频
Unity 2018.1中新增的众多功能之一是能够以与YouTube全景视频兼容的格式从相机拍摄屏幕截图。在Unity网站上的帖子中对此功能进行了简要描述:Stereo 360图像和视频捕获。不幸的是,其中没有用于测试的场景参考。
理论
通常,在运行游戏时会记录游戏剪辑。这适用于标准视频,但通常不适用于全景视频。主要原因是渲染全景游戏需要更大的面积,这会导致帧速率急剧下降。一种更标准的方法是在后台渲染和导出每个帧,以便以后可以在第三方软件(例如ffmpeg或Premiere Pro)中对其进行编辑。这就是我们将在本教程中执行的操作。
在Unity中渲染全景场景是一个非常简单的三步过程:
- 将场景渲染为立方体贴图纹理(Unity首选的全景纹理格式)
- 将立方体贴图转换为等角投影(YouTube全景视频的首选格式)
- 将等距投影另存为PNG
由于相机在Unity中的工作方式,前两个步骤是必需的。
如果您熟悉Unity,则可能知道存储全景纹理的首选方法是使用立方体贴图,这是一种包装六个不同图像而不会变形的方法(请参见下文)。立方贴图通常用于天空盒和反射探测器,因此您之前可能遇到过。
要创建全景纹理,Unity会六次渲染场景,每次以不同角度渲染。摄像机平移时就好像与立方体的六个侧面之一对齐。结果,每个全景屏幕截图都是链接在一起的六个传统屏幕截图。
填写立方体贴图后,第二步是将其转换为YouTube兼容格式。如前所述,YouTube需要等角全景视频。这种转换通常需要对复杂的着色器进行编码,但是幸运的是,Unity为此专门添加了一个功能。
最后一步将是将等距纹理导出到PNG文件。渲染完所有视频帧后,您可以使用ffmpeg或Premiere Pro等程序合并它们。
代码
第一步是创建一个脚本(在下面的代码片段中称为脚本
Camera360
),并将其附加到要渲染的相机上。但是,代码将根据我们是要以单声道(360°/单声道/ 2D)还是以立体声(VR /立体声/ 3D)渲染视频而改变。
单核细胞增多症
让我们从单声道版本开始:
public class Camera360 : MonoBehaviour
{
public Camera Camera;
public RenderTexture EyeCubemap;
public RenderTexture EquirectTexture;
void Update ()
{
Camera.RenderToCubemap(EyeCubemap, 63, Camera.MonoOrStereoscopicEye.Mono);
EyeCubemap.ConvertToEquirect(EquirectTexture, Camera.MonoOrStereoscopicEye.Mono);
}
}
上面的脚本将以称为的渲染纹理渲染每一帧
Equirect
,其中将包含保存在等角矩形投影中的全景屏幕截图。
该
63
方法中使用的值RenderToCubemap
意味着我们要从多维数据集的所有六个侧面截取屏幕截图。
两者
EyeCubemap
,并且EquirectTexture
可以在任何编辑器或代码中创建。
立体声
立体声版本代码非常相似,但是需要执行额外的步骤:
void Start ()
{
Camera.stereoSeparation = 0.064f; // 64mm
}
void Update ()
{
Camera.RenderToCubemap(EyeCubemap, 63, Camera.MonoOrStereoscopicEye.Left);
EyeCubemap.ConvertToEquirect(EquirectTexture, Camera.MonoOrStereoscopicEye.Left);
Camera.RenderToCubemap(EyeCubemap, 63, Camera.MonoOrStereoscopicEye.Right);
EyeCubemap.ConvertToEquirect(EquirectTexture, Camera.MonoOrStereoscopicEye.Right);
}
要渲染立体图像,您需要渲染两个立方体贴图。
stereoSeparation
设置这些立方体贴图之间的距离。标准值为64毫米,大约等于左眼和右眼之间的距离。
创建和保存纹理
上面的两个代码片段仅写入纹理,但是它们没有将其保存在任何地方。如果我们希望将帧保存到磁盘,则必须手动完成。
不幸的是,将渲染纹理导出到PNG文件并不容易。第一个问题是Unity不允许您直接访问单个像素
RenderTexture
。首先,需要将渲染纹理复制到object Texture2D
。
下面的代码段使用方法,正是
ReadPixels
从当前活动的渲染纹理复制像素来完全执行此任务。
public string FileName;
void Update ()
{
...
// Creates buffer
Texture2D tempTexture = new Texture2D(EquirectTexture.width, Equirect.height);
// Copies EquirectTexture into the tempTexture
RenderTexture currentActiveRT = RenderTexture.active;
RenderTexture.active = EquirectTexture;
TempTexture.ReadPixels(new Rect(0, 0, EquirectTexture.width, EquirectTexture.height), 0, 0);
// Exports to a PNG
var bytes = tempTexture.EncodeToPNG();
System.IO.File.WriteAllBytes(FileName, bytes);
// Restores the active render texture
RenderTexture.active = currentActiveRT;
}
只要它
FileName
包含正确的PNG文件路径,上述代码即可完成。只需做一个小更改:确保脚本不会一遍又一遍地覆盖同一文件。为此,只需将文件名计数器添加到重复重写中frame.png
,他正在写入中frame_0.png
,frame_1.png
等等。
问题
该解决方案存在问题。其中最重要的是某些后期处理效果可能无法按预期工作。
性能
在Unity中渲染全景框架是一项非常昂贵的任务。在我的解决方案中,场景被渲染了6或12次(取决于视频格式-单声道还是立体声)。合并图像并将每个帧保存到磁盘所需的后处理会将性能降低10-15倍。如果您以高质量(8192 x 8192像素)渲染视频,则每个单独的帧的大小都可能超过100 MB。显然,如果您没有非常强大的机器,您将无法同时实时播放和导出全景照片。
后期处理
例如,渐晕会在相机周围添加深色光晕。由于Unity通过六次渲染场景来创建全景图像,因此渐晕效果将应用于每个图像。结果,在图像的交界处将出现奇怪的黑晕。
同样,模糊和光晕效果也会在边缘引起错误,表明存在接缝。这个问题没有简单的解决方案,因为Unity创建的所有后处理堆栈都不适合用于全景图像。
但是,模糊和光晕效果仍然可以适度应用。如果需要这些效果,最好在使用Premiere Pro的后期制作中应用它们。
线渲染器
全景图像的一个巨大问题是线条渲染器可能无法正确显示。如果设置了一条线以使其必须始终看着相机,则在以全景图像进行渲染时,Unity会简单地丢弃它。这是非常令人讨厌的,因为没有真正的原因。
Unity开发了一种行式渲染器的替代版本,称为XRLineRenderer,它可以正常工作。尽管它不支持标准Line Renderer组件的所有功能,但您将能够实现大多数功能
XRLineRenderer还具有创建简单的发光效果的能力,这可以降低上一节中描述的问题的重要性。
也可以看看: