2

I have a simple Unity3D-scene for Oculus Rift and want to add ability to show his own desktop to a user(from main monitor). I've found that I can render it to a Texture2D, but how to efficiently capture a desktop?

Actually, I need to provide something like http://www.vrdesktop.net/, which allows to the user see his monitor's content inside VR. But I need to implement this as a library for Unity3D. So what is the best way to do that?

P.S. It would be nice to have a cross-platform solution, at least Windows and Linux/Mac.

dk14
  • 22,206
  • 4
  • 51
  • 88
  • What do you mean by dekstop? Do you want a screenshot of the unity editor (or some other app)? Do you want a one eyed version of the view? Also: what operating system? – Krzysztof Bociurko Nov 24 '14 at 07:53

2 Answers2

2

This one works (at least for Windows):

Texture2D tex = new Texture2D (200, 300, TextureFormat.RGB24, false);
Rectangle screenSize = System.Windows.Forms.Screen.PrimaryScreen.Bounds;
Bitmap target = new Bitmap (screenSize.Width, screenSize.Height);
using (System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(target)) {
  g.CopyFromScreen (0, 0, 0, 0, new Size (screenSize.Width, screenSize.Height));
}
MemoryStream ms = new MemoryStream ();
target.Save (ms, ImageFormat.Png);
ms.Seek (0, SeekOrigin.Begin);

tex.LoadImage (ms.ToArray ());

renderer.material.mainTexture = tex;

But efficiency is questionable here - every frame is converted to PNG, on the other hand capturing with CopyFromScreen works fine.

(Limitations) As it said in the Mono documentation: "Works on Win32 and on X11 (but not on Cocoa and Quartz)"

dk14
  • 22,206
  • 4
  • 51
  • 88
  • Could try with `ImageFormat.MemoryBMP` to `TextureFormat.RGB24`. – Krzysztof Bociurko Nov 26 '14 at 10:08
  • already tried, but it still a little bit slow (fine for most tasks but not so good for video); maybe there is a way to pass actual pointer to the tex, like `Texture2d.UpdateExternalTexture` (or even obtain someSystem.Drawing.Graphics object for texture). – dk14 Nov 26 '14 at 10:14
  • There is a [`LoadRawTextureData`](http://docs.unity3d.com/ScriptReference/Texture2D.LoadRawTextureData.html), fastest way i know to put new pixel data to a texture. Used it to load DXT and PVR data in the past, should also work for RBG24. Also it might be possible to use [`GetNativeTexturePtr` with a native plugin](http://docs.unity3d.com/Manual/NativePluginInterface.html) to copy the texture on the GPU. – Krzysztof Bociurko Nov 26 '14 at 11:43
  • Hmm. I'm getting "UnityException: LoadRawTextureData: not enough data provided (will result in overread)." error - even with mipmap = false and MemoryBMP+RGB24 – dk14 Nov 26 '14 at 19:34
  • Quick checklist: 1. Have you set width/height of the unity's texture? 2. What is the size in bytes of the retrieved texture data, is it width*height*3? If it's something else then it could be a 32bit RGBA or 16 bit RGB565. This might be dependent on system settings. – Krzysztof Bociurko Nov 26 '14 at 19:55
  • How did you use Bitmap? – pookie May 07 '16 at 19:26
0

I believe Unity3D does not have this sort of functionality. If you want to be able to interact with your desktop, you would use remote desktop software. If you want to grab your desktop view, you can use screen capturing/recording software. Else, you will have to use an incredibly complex or gimmicky method to integrate this into Unity. One of the comments here was quite informative.

Andy
  • 2,374
  • 3
  • 17
  • 20
  • Mono has such functionality (at least for Windows) - http://stackoverflow.com/questions/397754/record-video-of-screen-using-net-technologies – dk14 Nov 24 '14 at 18:57