ã¯ããã«
以ä¸ã®ã¨ã³ããªã§ã¯ã¹ã¯ãªã¼ã³ãã£ããã£ã System.Drawing.Graphics.CopyFromScreen() ãå¥ã¹ã¬ããã§åãã¦è¡ã£ã¦ãã¾ããã
ããã§è§¦ãããã¦ããããã«ãã¤ãã£ãã§ãã£ãæ¹ãéãã¨ãããã¨ããããæ¬ã¨ã³ããªã§ã¯ Windows 8 ãã使ãã Desktop Duplication API ãå©ç¨ããã¹ã¯ãªã¼ã³ãã£ããã£ã®ç°¡åãªãµã³ãã«ãç´¹ä»ãã¾ãã
ç°å¢
- Windows 8.1
- Unity 5.3.0f4
çµæ

ãµã³ãã«
追è¨ï¼2016/10/28ï¼
Github ã«æ´çãããã®ãä¸ãã¾ããã
æ¦è¦
DirectX 11 ããã³ Low-Level Native Plugin Interface ãéãã¦ãã¯ã¹ãã£ãåå¾ãã¾ãã®ã§ã詳細ã«ã¤ãã¦ã¯ä»¥ä¸ã®ã¨ã³ããªããåç §ä¸ããã
Desktop Duplication API ã¯ä»¥ä¸ã«è©³ç´°ãã¾ã¨ãããã¦ãã¾ãã
IDXGIOutputDuplication::AcquireNextFrame() ãéãã¦ãã¯ã¹ãã£ããã¦ã¹ã®æ
å ±ãªã©ãåãåããã®ã§ãIDXGIOutputDuplication ã®ã¤ã³ã¹ã¿ã³ã¹ãã¡ã¤ã³ãã£ã¹ãã¬ã¤ã¨ãªã IDXGIOutput1 ããåå¾ããæ¯ãã¬ã¼ã ãã®é¢æ°ãå¼ãã§ Unity å´ã®ãã¯ã¹ãã£ã¸ã¨åæ ãã¾ãã
C++ å´ã®ã³ã¼ã
#include <d3d11.h> #include <dxgi1_2.h> #include "IUnityInterface.h" #include "IUnityGraphics.h" #include "IUnityGraphicsD3D11.h" #pragma comment(lib, "dxgi.lib") namespace { IUnityInterfaces* g_unity = nullptr; IDXGIOutputDuplication* g_deskDupl = nullptr; ID3D11Texture2D* g_texture = nullptr; bool g_isPointerVisible = false; int g_pointerX = -1; int g_pointerY = -1; int g_width = -1; int g_height = -1; } extern "C" { UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API UnityPluginLoad(IUnityInterfaces* unityInterfaces) { g_unity = unityInterfaces; IDXGIFactory1* factory; CreateDXGIFactory1(__uuidof(IDXGIFactory1), reinterpret_cast<void**>(&factory)); // å ¨ãã£ã¹ãã¬ã¤ã¢ããã¿ã調ã¹ã IDXGIAdapter1* adapter; for (int i = 0; (factory->EnumAdapters1(i, &adapter) != DXGI_ERROR_NOT_FOUND); ++i) { // ã¢ã¦ãããããä¸éã調ã¹ã¦ã¡ã¤ã³ã¢ãã¿ãæ¢ã IDXGIOutput* output; for (int j = 0; (adapter->EnumOutputs(j, &output) != DXGI_ERROR_NOT_FOUND); j++) { DXGI_OUTPUT_DESC outputDesc; output->GetDesc(&outputDesc); MONITORINFOEX monitorInfo; monitorInfo.cbSize = sizeof(MONITORINFOEX); GetMonitorInfo(outputDesc.Monitor, &monitorInfo); if (monitorInfo.dwFlags == MONITORINFOF_PRIMARY) { g_width = monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left; g_height = monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top; auto device = g_unity->Get<IUnityGraphicsD3D11>()->GetDevice(); IDXGIOutput1* output1; output1 = reinterpret_cast<IDXGIOutput1*>(output); output1->DuplicateOutput(device, &g_deskDupl); output->Release(); adapter->Release(); factory->Release(); return; } output->Release(); } adapter->Release(); } factory->Release(); } UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API UnityPluginUnload() { g_unity = nullptr; g_deskDupl->Release(); g_deskDupl = nullptr; g_texture = nullptr; g_isPointerVisible = false; g_width = -1; g_height = -1; g_pointerX = -1; g_pointerY = -1; } void UNITY_INTERFACE_API OnRenderEvent(int eventId) { if (g_deskDupl == nullptr || g_texture == nullptr) return; IDXGIResource* resource = nullptr; DXGI_OUTDUPL_FRAME_INFO frameInfo; const UINT timeout = 500; // ms g_deskDupl->AcquireNextFrame(timeout, &frameInfo, &resource); g_isPointerVisible = frameInfo.PointerPosition.Visible; g_pointerX = frameInfo.PointerPosition.Position.x; g_pointerY = frameInfo.PointerPosition.Position.y; ID3D11Texture2D* texture; resource->QueryInterface(__uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&texture)); resource->Release(); ID3D11DeviceContext* context; auto device = g_unity->Get<IUnityGraphicsD3D11>()->GetDevice(); device->GetImmediateContext(&context); context->CopyResource(g_texture, texture); g_deskDupl->ReleaseFrame(); } UNITY_INTERFACE_EXPORT UnityRenderingEvent UNITY_INTERFACE_API GetRenderEventFunc() { return OnRenderEvent; } UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API GetWidth() { return g_width; } UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API GetHeight() { return g_height; } UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API IsPointerVisible() { return g_isPointerVisible; } UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API GetPointerX() { return g_pointerX; } UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API GetPointerY() { return g_pointerY; } UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API SetTexturePtr(void* texture) { g_texture = reinterpret_cast<ID3D11Texture2D*>(texture); } }
Unity å´ã®ã³ã¼ãï¼C#ï¼
using UnityEngine; using System; using System.Collections; using System.Runtime.InteropServices; public class DesktopCapture : MonoBehaviour { [DllImport ("DesktopCapture")] private static extern int GetWidth(); [DllImport ("DesktopCapture")] private static extern int GetHeight(); [DllImport ("DesktopCapture")] private static extern bool IsPointerVisible(); [DllImport ("DesktopCapture")] private static extern int GetPointerX(); [DllImport ("DesktopCapture")] private static extern int GetPointerY(); [DllImport ("DesktopCapture")] private static extern int SetTexturePtr(IntPtr ptr); [DllImport ("DesktopCapture")] private static extern IntPtr GetRenderEventFunc(); public bool isPointerVisible = false; public int pointerX = 0; public int pointerY = 0; void Start() { var tex = new Texture2D(GetWidth(), GetHeight(), TextureFormat.BGRA32, false); GetComponent<Renderer>().material.mainTexture = tex; SetTexturePtr(tex.GetNativeTexturePtr()); StartCoroutine(OnRender()); } void Update() { isPointerVisible = IsPointerVisible(); pointerX = GetPointerX(); pointerY = GetPointerY(); } IEnumerator OnRender() { for (;;) { yield return new WaitForEndOfFrame(); GL.IssuePluginEvent(GetRenderEventFunc(), 0); } } }
ãããã«
Virtual Desktop ã¿ãããªã¢ããªãããã§ä½ããã®ã§ã¯ãªãã§ããããã