使用 VideoPlayer 播放 360 度立体视频
Play 360 Stereoscopic video with VideoPlayer
我想在 Android 上的 Unity 虚拟现实中播放立体 360 度视频。到目前为止,我一直在做一些研究,我有两个摄像头用于右眼和左眼,每个摄像头周围都有一个球体。我还需要一个自定义着色器来使图像渲染在球体内部。通过将 y 平铺设置为 0.5,我将图像的上半部分显示在一个球体上,下半部分显示在另一个球体上,y 平铺设置为 0.5,y 偏移量为 0.5。 有了这个,我可以显示已经正确的 3D 360 度图像。整个想法来自this tutorial.
现在对于视频,我需要控制视频速度,所以 我需要来自新的 Unity 5.6 beta 的 VideoPlayer。现在我的设置要求视频播放器在两个球体上播放视频,一个球体播放上半部分(一只眼睛),另一个视频播放下半部分(另一只眼睛)。
这是我的问题:我不知道如何让视频播放器在两个不同的 material 上播放相同的视频(因为它们有不同的平铺值)。有办法吗?
我得到一个提示,我可以使用相同的 material 并通过 UV 实现平铺效果,但我不知道它是如何工作的,我什至没有视频播放器来播放两个对象上的视频使用相同的 material。我有一个截图 of that here。右球体只有 material videoMaterial。没有平铺,因为我必须通过紫外线来做到这一点。
走哪条路,怎么做?我走对了吗?
Am I on the right way here?
差不多,但是您目前使用的是 Renderer
和 Material
,而不是 RenderTexture
和 Material
。
Which way to go and how to do it?
您需要为此使用 RenderTexture
。基本上,您将视频渲染到 RenderTexture
,然后将该纹理分配给两个球体的 material。
1.创建一个RenderTexture
并将其分配给VideoPlayer
.
2。为球体创建两个 material。
3.将VideoPlayer.renderMode
设为VideoRenderMode.RenderTexture;
4.将两个球体的纹理设置为RenderTexture
中的纹理
5。准备和播放视频。
下面的代码就是在做这件事。它应该开箱即用。您唯一需要做的就是根据您的需要修改每个 material 的平铺和偏移量。
你也应该注释掉:
leftSphere = createSphere("LeftEye", new Vector3(-5f, 0f, 0f), new Vector3(4f, 4f, 4f));
rightSphere = createSphere("RightEye", new Vector3(5f, 0f, 0f), new Vector3(4f, 4f, 4f));
然后使用从任何 3D 应用程序导入的球体。该行代码仅用于测试目的,使用 Unity 的球体播放视频不是一个好主意,因为球体没有足够的细节来使视频流畅。
using UnityEngine;
using UnityEngine.Video;
public class StereoscopicVideoPlayer : MonoBehaviour
{
RenderTexture renderTexture;
Material leftSphereMat;
Material rightSphereMat;
public GameObject leftSphere;
public GameObject rightSphere;
private VideoPlayer videoPlayer;
//Audio
private AudioSource audioSource;
void Start()
{
//Create Render Texture
renderTexture = createRenderTexture();
//Create Left and Right Sphere Materials
leftSphereMat = createMaterial();
rightSphereMat = createMaterial();
//Create the Left and Right Sphere Spheres
leftSphere = createSphere("LeftEye", new Vector3(-5f, 0f, 0f), new Vector3(4f, 4f, 4f));
rightSphere = createSphere("RightEye", new Vector3(5f, 0f, 0f), new Vector3(4f, 4f, 4f));
//Assign material to the Spheres
leftSphere.GetComponent<MeshRenderer>().material = leftSphereMat;
rightSphere.GetComponent<MeshRenderer>().material = rightSphereMat;
//Add VideoPlayer to the GameObject
videoPlayer = gameObject.AddComponent<VideoPlayer>();
//Add AudioSource
audioSource = gameObject.AddComponent<AudioSource>();
//Disable Play on Awake for both Video and Audio
videoPlayer.playOnAwake = false;
audioSource.playOnAwake = false;
// We want to play from url
videoPlayer.source = VideoSource.Url;
videoPlayer.url = "http://www.quirksmode.org/html5/videos/big_buck_bunny.mp4";
//Set Audio Output to AudioSource
videoPlayer.audioOutputMode = VideoAudioOutputMode.AudioSource;
//Assign the Audio from Video to AudioSource to be played
videoPlayer.EnableAudioTrack(0, true);
videoPlayer.SetTargetAudioSource(0, audioSource);
//Set the mode of output to be RenderTexture
videoPlayer.renderMode = VideoRenderMode.RenderTexture;
//Set the RenderTexture to store the images to
videoPlayer.targetTexture = renderTexture;
//Set the Texture of both Spheres to the Texture from the RenderTexture
assignTextureToSphere();
//Prepare Video to prevent Buffering
videoPlayer.Prepare();
//Subscribe to prepareCompleted event
videoPlayer.prepareCompleted += OnVideoPrepared;
}
RenderTexture createRenderTexture()
{
RenderTexture rd = new RenderTexture(1024, 1024, 16, RenderTextureFormat.ARGB32);
rd.Create();
return rd;
}
Material createMaterial()
{
return new Material(Shader.Find("Specular"));
}
void assignTextureToSphere()
{
//Set the Texture of both Spheres to the Texture from the RenderTexture
leftSphereMat.mainTexture = renderTexture;
rightSphereMat.mainTexture = renderTexture;
}
GameObject createSphere(string name, Vector3 spherePos, Vector3 sphereScale)
{
GameObject sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);
sphere.transform.position = spherePos;
sphere.transform.localScale = sphereScale;
sphere.name = name;
return sphere;
}
void OnVideoPrepared(VideoPlayer source)
{
Debug.Log("Done Preparing Video");
//Play Video
videoPlayer.Play();
//Play Sound
audioSource.Play();
//Change Play Speed
if (videoPlayer.canSetPlaybackSpeed)
{
videoPlayer.playbackSpeed = 1f;
}
}
}
还有 Unity tutorial 关于如何使用特殊着色器执行此操作的内容,但这对我和其他一些人不起作用。我建议您使用上面的方法,直到 VideoPlayer
API.
添加了 VR 支持
我想在 Android 上的 Unity 虚拟现实中播放立体 360 度视频。到目前为止,我一直在做一些研究,我有两个摄像头用于右眼和左眼,每个摄像头周围都有一个球体。我还需要一个自定义着色器来使图像渲染在球体内部。通过将 y 平铺设置为 0.5,我将图像的上半部分显示在一个球体上,下半部分显示在另一个球体上,y 平铺设置为 0.5,y 偏移量为 0.5。 有了这个,我可以显示已经正确的 3D 360 度图像。整个想法来自this tutorial.
现在对于视频,我需要控制视频速度,所以
这是我的问题:我不知道如何让视频播放器在两个不同的 material 上播放相同的视频(因为它们有不同的平铺值)。有办法吗?
我得到一个提示,我可以使用相同的 material 并通过 UV 实现平铺效果,但我不知道它是如何工作的,我什至没有视频播放器来播放两个对象上的视频使用相同的 material。我有一个截图 of that here。右球体只有 material videoMaterial。没有平铺,因为我必须通过紫外线来做到这一点。
走哪条路,怎么做?我走对了吗?
Am I on the right way here?
差不多,但是您目前使用的是 Renderer
和 Material
,而不是 RenderTexture
和 Material
。
Which way to go and how to do it?
您需要为此使用 RenderTexture
。基本上,您将视频渲染到 RenderTexture
,然后将该纹理分配给两个球体的 material。
1.创建一个RenderTexture
并将其分配给VideoPlayer
.
2。为球体创建两个 material。
3.将VideoPlayer.renderMode
设为VideoRenderMode.RenderTexture;
4.将两个球体的纹理设置为RenderTexture
5。准备和播放视频。
下面的代码就是在做这件事。它应该开箱即用。您唯一需要做的就是根据您的需要修改每个 material 的平铺和偏移量。
你也应该注释掉:
leftSphere = createSphere("LeftEye", new Vector3(-5f, 0f, 0f), new Vector3(4f, 4f, 4f));
rightSphere = createSphere("RightEye", new Vector3(5f, 0f, 0f), new Vector3(4f, 4f, 4f));
然后使用从任何 3D 应用程序导入的球体。该行代码仅用于测试目的,使用 Unity 的球体播放视频不是一个好主意,因为球体没有足够的细节来使视频流畅。
using UnityEngine;
using UnityEngine.Video;
public class StereoscopicVideoPlayer : MonoBehaviour
{
RenderTexture renderTexture;
Material leftSphereMat;
Material rightSphereMat;
public GameObject leftSphere;
public GameObject rightSphere;
private VideoPlayer videoPlayer;
//Audio
private AudioSource audioSource;
void Start()
{
//Create Render Texture
renderTexture = createRenderTexture();
//Create Left and Right Sphere Materials
leftSphereMat = createMaterial();
rightSphereMat = createMaterial();
//Create the Left and Right Sphere Spheres
leftSphere = createSphere("LeftEye", new Vector3(-5f, 0f, 0f), new Vector3(4f, 4f, 4f));
rightSphere = createSphere("RightEye", new Vector3(5f, 0f, 0f), new Vector3(4f, 4f, 4f));
//Assign material to the Spheres
leftSphere.GetComponent<MeshRenderer>().material = leftSphereMat;
rightSphere.GetComponent<MeshRenderer>().material = rightSphereMat;
//Add VideoPlayer to the GameObject
videoPlayer = gameObject.AddComponent<VideoPlayer>();
//Add AudioSource
audioSource = gameObject.AddComponent<AudioSource>();
//Disable Play on Awake for both Video and Audio
videoPlayer.playOnAwake = false;
audioSource.playOnAwake = false;
// We want to play from url
videoPlayer.source = VideoSource.Url;
videoPlayer.url = "http://www.quirksmode.org/html5/videos/big_buck_bunny.mp4";
//Set Audio Output to AudioSource
videoPlayer.audioOutputMode = VideoAudioOutputMode.AudioSource;
//Assign the Audio from Video to AudioSource to be played
videoPlayer.EnableAudioTrack(0, true);
videoPlayer.SetTargetAudioSource(0, audioSource);
//Set the mode of output to be RenderTexture
videoPlayer.renderMode = VideoRenderMode.RenderTexture;
//Set the RenderTexture to store the images to
videoPlayer.targetTexture = renderTexture;
//Set the Texture of both Spheres to the Texture from the RenderTexture
assignTextureToSphere();
//Prepare Video to prevent Buffering
videoPlayer.Prepare();
//Subscribe to prepareCompleted event
videoPlayer.prepareCompleted += OnVideoPrepared;
}
RenderTexture createRenderTexture()
{
RenderTexture rd = new RenderTexture(1024, 1024, 16, RenderTextureFormat.ARGB32);
rd.Create();
return rd;
}
Material createMaterial()
{
return new Material(Shader.Find("Specular"));
}
void assignTextureToSphere()
{
//Set the Texture of both Spheres to the Texture from the RenderTexture
leftSphereMat.mainTexture = renderTexture;
rightSphereMat.mainTexture = renderTexture;
}
GameObject createSphere(string name, Vector3 spherePos, Vector3 sphereScale)
{
GameObject sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);
sphere.transform.position = spherePos;
sphere.transform.localScale = sphereScale;
sphere.name = name;
return sphere;
}
void OnVideoPrepared(VideoPlayer source)
{
Debug.Log("Done Preparing Video");
//Play Video
videoPlayer.Play();
//Play Sound
audioSource.Play();
//Change Play Speed
if (videoPlayer.canSetPlaybackSpeed)
{
videoPlayer.playbackSpeed = 1f;
}
}
}
还有 Unity tutorial 关于如何使用特殊着色器执行此操作的内容,但这对我和其他一些人不起作用。我建议您使用上面的方法,直到 VideoPlayer
API.