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 OnMouseDown() {
        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

时间: 2024-08-07 03:15:05

VR中特定相机截屏问题与实现的相关文章

unity3d 3中截屏方法

每天一点知识点(Unity中三种截屏方法)热度 231388 2015-9-1 11:29 |个人分类:学习笔记| 知识点, 截屏 /// <summary> /// 截取全屏的方法包括UI /// </summary> public void CaptureScreen() { Application.CaptureScreenshot("截取全屏.png", 0); Debug.Log(1); } /// <summary> /// 自定义截图大

项目总结之截屏细节考虑

DionysosLai([email protected]) 2014/12/22 2014项目总算告一段落,这个产品顺顺利利从开始到最后的上市,圆满成功.借着项目总结,回顾自己做的几个游戏,将一些细节问题归纳.第一篇,就以目前正在做的的新游戏<圣诞节>开篇,讲讲游戏截屏问题. 对于截屏,本身技术,并不是很复杂,一般有两种方法,一种是使用Opengl像素取点方式:另一种是使用RenderTexture纹理方法,详细内容,可以参考,之前写的一篇文章:http://blog.csdn.net/di

截屏 多难未遂

看到未遂,就知道这只是一篇分享感受的文章,但是,或多或少,有过同样过程的人至少会有一点同感..或有一点思路以及灵感. 其实网上关于截屏的demo很多,以及思路也很多.我也不知道自己是哪里出了问题,总是未遂. 但是还是有几个值得注意的: 不管什么FrameBuffer呀,还是Android源码里面截屏的ScreenShot..还是ScreenControll...and...这里要去掏Android更深,更底层或是最原始的都是需要root的...但是,本人root真不是很在行. 开始,我问了很多大

对相机所看的视角截屏保存为图片

对相机所看的视角截屏保存为图片: 1 using UnityEngine; 2 using System.Collections; 3 using UnityEngine.UI; 4 /// <summary> 5 /// 对相机截图 6 /// </summary> 7 public class Jietu : MonoBehaviour { 8 9 public Camera camera; 10 Texture2D tex; 11 void Start() 12 { 13 t

iOS中的截屏(屏幕截屏及scrollView或tableView的全部截屏)

iOS中的截屏(屏幕截屏及scrollView或tableView的全部截屏) 2017.03.16 12:18* 字数 52 阅读 563评论 4喜欢 2 1. 截取屏幕尺寸大小的图片并保存至相册 保存至相册只需将方法saveImage中的代码替换即可 UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, YES, 0.0); [self.view.layer renderInContext:UIGraphicsGetCur

应用内截屏的代码,在Activity中测试可用

截屏功能让我十分头疼,想做个无需root的又找不到资料.这里暂且分享一个无需root的,在应用内截屏的代码,本文转自:http://blog.csdn.net/csh159/article/details/7876415   截图后→   布局文件: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/

Android中利用命令行进行截屏并导出到电脑上

声明:本博客为原创博客,未经允许,不得转载!原文链接为http://blog.csdn.net/bettarwang/article/details/27819525 大多数人最常用的截屏方法可能就是利用手机的快捷按键了,但是那样如果要导入到电脑中效率会比较低.实际上有更好的截屏方式,最简单的当然就是利用Eclipse中的DDMS进行截屏了,点击"Screen Capture"按钮后等待10多秒,然后就可直接利用Save按钮保存到电脑中. 显然,由于要进行图片显示的原因,在DDMS中会

js利用clipboardData在网页中实现截屏粘贴的功能

目前仅有高版本的 Chrome 浏览器支持这样直接粘贴,其他浏览器目前为止还无法粘贴,不过火狐和ie11浏览器在可编辑的div中能够粘贴截图的图片也是base64位和Chrome利用clipboardData的效果是一样的,只是在火狐和ie11浏览器中目前还无法实现类似用clipboardData直接获取图片的base64数据,它是自带的直接进去img数据 完整实例: <!DOCTYPE HTML><html lang="en-US"><head>&

Python中的截屏模块 pyscreenshot

前言 pyscreenshot 是一个 Python 的模块,用来对屏幕进行截屏并拷贝到 PIL or Pillow 图像对象中.这是一个纯 Python 库,支持跨平台. 示例代码: import pyscreenshot as ImageGrab fullscreen im=ImageGrab.grab() im.show() part of the screen im=ImageGrab.grab(bbox=(10,10,510,510)) # X1,Y1,X2,Y2 im.show()