首页 > 代码库 > VR中特定相机截屏问题与实现
VR中特定相机截屏问题与实现
本文章由cartzhang编写,转载请注明出处。 所有权利保留。
文章链接:http://blog.csdn.net/cartzhang/article/details/71136498
作者:cartzhang
unity 中的截图与VR中的截图,难度还不一样么?还真有点不一样。
这里就是用HTC Vive头盔下来做为例子。
非常感谢同事让我来帮他解决问题。
一、Unity中的常用截图方式
unity中常用截图的方式有三种:
1. 使用CaptureScreenshot
这个可以参考官方给的例子和代码
https://docs.unity3d.com/ScriptReference/Application.CaptureScreenshot.html
void onm ouseDown() {
Application.CaptureScreenshot("Screenshot.png");
}
很简单快捷,就是截取当前屏幕的画面。对于某个镜头的画面或针对场景中位置的截图,这个就不其作用了。
2. 使用RenderTexture
这个是使用相机来渲染画面,根据相机的画面来保持纹理,把纹理保存为图片。
可以参考我之前翻译的文章,发布于蛮牛社区。
http://www.manew.com/thread-45355-1-1.html
代码都有,我这里就不重复的粘帖了。
要注意的是在LateUpdate中做了截图的处理;
void LateUpdate()
{
if (Input.GetKeyDown("s"))
{
StartCoroutine(SaveCameraView());
}
}
3. 使用Texture2D.ReadPixels
这个也是新建一个Texture2D,然后ReadPixels,z这个是也从屏幕来读取数据。
所以也有屏幕读取数据的局限。
Texture2D tex = new Texture2D(Screen.width, Screen.height);
tex.ReadPixels(new Rect(0,0,Screen.width,Screen.height),0,0);
tex.Apply();
三种方式对比,第二种———使用RenderTexture速度最快。可以参考后面的网站。
二、 VR截图注意事项
1. VR中特位置截图
对于截取VR中,若截取全屏使用上面的任意方法都可以。
但是VR的特点就是相机有玩家来控制,不知道玩家相机的朝向和位置。这个就需要固定位置的截图。
某个固定位置对象来说,只能使用RenderTexture来实现。
这个里面有两个问题。
第一,VR相机的旋转是灵活的,且在vive中,硬件头盔会控制所有相机的旋转。
第二,就是不能使用于屏幕相关的参数,因为屏幕大小在不一定。
这里的问题,我们就逐一来解决和说明。
2.实现代码
首先,创建一个RenderTexture,这个做为public,有外面拖拽,在外面定义的RenderTexture来创建好大小和格式。这样容易控制图片大小和格式,策划容易修改。
其次,解决VR相机能控制所有相机的问题,不能在特定位置预先放置相机,然后在某时刻获取RenderTexture,虽然也可成功截图,但是可能由于相机的角度不停在改变,造成截图移位或倾斜。
在代码中实时的创建相机。
代码如下:
private IEnumerator CaptureByRect(string mFileName)
{
//等待渲染线程结束
yield return new WaitForEndOfFrame();
// 实时来创建相机,硬件相机来不及绑定,不会造成偏移和旋转。
GameObject gob = new GameObject();
gob.transform.position = CameraTrans[0].transform.position;
gob.AddComponent<Camera>();
Camera mCamera = gob.GetComponent<Camera>();
// 相机投影为正射投影,防止变形和策划调整难度大。
mCamera.orthographic = true;
mCamera.farClipPlane = 20;
mCamera.orthographicSize = 5f;
mCamera.transform.rotation = new Quaternion(0, 0, 0, 0);
//mCamera.cullingMask = 1 << 5;
mCamera.targetTexture = shotTexture;
// get the camera‘s render texture
RenderTexture.active = mCamera.targetTexture;
// render the texture
mCamera.Render();
int height = mCamera.targetTexture.height;
Texture2D cameraImage = new Texture2D(55, 57, TextureFormat.RGB24, false);
cameraImage.ReadPixels(new Rect(100, 105, 55, 57), 0, 0);
cameraImage.Apply();
// store the texture into a .PNG file
byte[] bytes = cameraImage.EncodeToPNG();
System.IO.File.WriteAllBytes(mFileName, bytes);
Destroy(gob);
//等待渲染线程结束
yield return new WaitForEndOfFrame();
AssetDatabase.Refresh();
}
这里面使用RenderTexture大小为256*256的,根据截图大小来确定Texture读取像素位置。
这里的代码注释写的还算详细,也容易看懂就不多说了。
3. 关于改进
关于保存图片,这个在使用有卡顿现象。
试图使用线程来解决,但是策划说效果不明显,还不如不使用。
new System.Threading.Thread(() =>
{
System.Threading.Thread.Sleep(100);
System.IO.File.WriteAllBytes(mFileName, bytes);
}).Start();
个人感觉,线程没有问题,可能是创建线程需要时间,可以尝试使用线程池来。
steamVR中的也有带截屏的函数,可以截出立体效果,这个希望能抽时间研究下!
三、参考
【1】https://ralphbarbagallo.com/2012/04/09/3-ways-to-capture-a-screenshot-in-unity3d/
【2】 https://docs.unity3d.com/ScriptReference/Application.CaptureScreenshot.html
【3】 http://www.manew.com/thread-45355-1-1.html
【4】 http://stackoverflow.com/questions/36186209/take-screenshot-in-unity3d-with-no-lags
VR中特定相机截屏问题与实现