Как эффективно и кроссплатформенно захватить текущий рабочий стол в Unity3D?

У меня есть простая Unity3D-сцена для Oculus Rift, и я хочу добавить возможность показывать пользователю свой рабочий стол (с основного монитора). Я обнаружил, что могу преобразовать его в Texture2D, но как эффективно захватить рабочий стол?

На самом деле мне нужно предоставить что-то вроде http://www.vrdesktop.net/, что позволяет пользователю видеть содержимое своего монитора внутри виртуальной реальности. Но мне нужно реализовать это как библиотеку для Unity3D. Итак, как лучше всего это сделать?

P.S. Было бы неплохо иметь кроссплатформенное решение, хотя бы для Windows и Linux/Mac.


person dk14    schedule 24.11.2014    source источник
comment
Что вы имеете в виду под десктопом? Хотите скриншот редактора единства (или другого приложения)? Вы хотите одноглазую версию представления? Также: какая операционная система?   -  person Krzysztof Bociurko    schedule 24.11.2014


Ответы (2)


Это работает (по крайней мере, для 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;

Но эффективность тут под вопросом - каждый кадр конвертируется в PNG, зато захват с CopyFromScreen работает нормально.

(Ограничения) Как сказано в документации Mono: "Работает на Win32 и X11 (но не на Cocoa и Quartz)"

person dk14    schedule 24.11.2014
comment
Можно попробовать с ImageFormat.MemoryBMP на TextureFormat.RGB24. - person Krzysztof Bociurko; 26.11.2014
comment
уже попробовал, но он все еще немного медленный (хорошо для большинства задач, но не так хорошо для видео); возможно, есть способ передать фактический указатель на текст, например Texture2d.UpdateExternalTexture (или даже получить какой-либо объект System.Drawing.Graphics для текстуры). - person dk14; 26.11.2014
comment
Существует LoadRawTextureData, самый быстрый известный мне способ поместить новые пиксельные данные в текстура. Раньше использовал его для загрузки данных DXT и PVR, также должен работать для RBG24. Также может быть возможно использовать GetNativeTexturePtr со встроенным плагином для копирования текстуры на ГП. - person Krzysztof Bociurko; 26.11.2014
comment
Хм. Я получаю UnityException: LoadRawTextureData: предоставлено недостаточно данных (приведет к перечтению). ошибка - даже с mipmap = false и MemoryBMP+RGB24 - person dk14; 26.11.2014
comment
Краткий контрольный список: 1. Вы установили ширину/высоту текстуры единства? 2. Каков размер в байтах извлеченных данных текстуры, это ширина*высота*3? Если это что-то другое, то это может быть 32-битный RGBA или 16-битный RGB565. Это может зависеть от настроек системы. - person Krzysztof Bociurko; 26.11.2014
comment
Как вы использовали Bitmap? - person pookie; 07.05.2016

Я считаю, что Unity3D не имеет такой функциональности. Если вы хотите иметь возможность взаимодействовать со своим рабочим столом, вы должны использовать программное обеспечение для удаленного рабочего стола. Если вы хотите получить вид рабочего стола, вы можете использовать программное обеспечение для захвата/записи экрана. В противном случае вам придется использовать невероятно сложный или бесполезный метод для интеграции этого в Unity. Один из комментариев здесь был весьма информативен.

person Andy    schedule 24.11.2014
comment
У Mono есть такая функциональность (по крайней мере, для Windows) - stackoverflow.com/questions/397754/ - person dk14; 24.11.2014