Compare commits

..

14 Commits

Author SHA1 Message Date
hecomi
f8146c15bd update readme. 2016-10-28 19:33:45 +09:00
hecomi
d5a9827b4d add toggle example. 2016-10-28 19:33:37 +09:00
hecomi
4b499a96de update readme. 2016-10-28 19:23:10 +09:00
hecomi
583326c333 add license. 2016-10-28 19:09:42 +09:00
hecomi
c3ec17dd7b add shader example. 2016-10-28 19:08:08 +09:00
hecomi
6f375e2e5b change class names. / add multiple screen example. / performance tuning. 2016-10-28 18:48:53 +09:00
hecomi
d9f83cf89e implement multiple screen. 2016-10-28 17:28:22 +09:00
hecomi
ba5ebe8094 update readme. 2016-10-27 19:19:45 +09:00
hecomi
1e2ac40507 support linear color. 2016-10-27 19:18:44 +09:00
hecomi
de0c157fb5 update readme. 2016-10-27 18:53:36 +09:00
hecomi
c93bd58ec4 modify default shader. 2016-10-27 18:51:10 +09:00
hecomi
c4db1ab14a add shader family. 2016-10-27 18:50:45 +09:00
hecomi
e72eff0ee7 add mouse cursor. 2016-10-27 18:17:37 +09:00
hecomi
50fd042e35 update readme. 2016-10-27 16:33:39 +09:00
61 changed files with 1071 additions and 137 deletions

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 678e1de5e6de7914baed516a78940503
folderAsset: yes
timeCreated: 1477643728
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: de6f36e446e5e8a48bf61fe198985bb4
timeCreated: 1477643732
licenseType: Pro
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 0a3456d4b2f59e84f969e31deca4016d
folderAsset: yes
timeCreated: 1477643596
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 445860b05342be845967392bfd70224e
timeCreated: 1477643648
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 281e2991d4d33984fa180845e56cd3f3
timeCreated: 1477648643
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f66b67cb0e751dc4ca0251b38bc8638d
timeCreated: 1477648784
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 78e54899a518eb749a589b921a1b263f
timeCreated: 1477650252
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 71921882396f0f345aa8a66e2fcb0b6c
folderAsset: yes
timeCreated: 1477643608
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,20 @@
using UnityEngine;
public class MultipleMonitorCreator : MonoBehaviour
{
[SerializeField] GameObject monitorPrefab;
[SerializeField] Vector3 margin = new Vector3(20f, 0f, 0f);
void Start()
{
var monitors = uDesktopDuplication.Manager.monitors;
var n = monitors.Count;
for (int i = 0 ; i < n; ++i) {
var go = Instantiate(monitorPrefab);
go.transform.position = transform.position + margin * (i - n / 2f + 0.5f);
var texture = go.GetComponent<uDesktopDuplication.Texture>();
texture.monitorId = i;
}
}
}

View File

@@ -1,6 +1,6 @@
fileFormatVersion: 2
guid: bb54a34570e4747429b1c5b66c69d356
timeCreated: 1452445649
guid: fb22986017201f74aa864dcbf0cab751
timeCreated: 1477643778
licenseType: Pro
MonoImporter:
serializedVersion: 2

View File

@@ -0,0 +1,17 @@
using UnityEngine;
public class ToggleMonitors : MonoBehaviour
{
void Update()
{
if (Input.GetKeyDown(KeyCode.Tab)) {
var texture = GetComponent<uDesktopDuplication.Texture>();
if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift)) {
texture.monitorId--;
} else {
texture.monitorId++;
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 602d3a9bed585d14eaf21e0528d24d54
timeCreated: 1477650268
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 033e0db89e0ca1d46a399c953629f67d
timeCreated: 1477555367
licenseType: Pro
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 06ef13d14bbcf9242a8eba19a94803f3
timeCreated: 1477648806
licenseType: Pro
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 3abaadab838fb3c4ba342eda7431d4f7
timeCreated: 1477648806
licenseType: Pro
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 647550562f402264fb69871ec732b74c
timeCreated: 1477648806
licenseType: Pro
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 6e15bc51aada81042a909c808e25c176
folderAsset: yes
timeCreated: 1477555207
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 48b92326b146fa848beec6f35365b1f4
folderAsset: yes
timeCreated: 1477555207
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: a615a0cde495b914d95b9d2d53182305
folderAsset: yes
timeCreated: 1477555207
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 967 B

View File

@@ -0,0 +1,59 @@
fileFormatVersion: 2
guid: 89616e59e1cccb346bd4e959257990ca
timeCreated: 1477555207
licenseType: Pro
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 2
mipmaps:
mipMapMode: 0
enableMipMap: 0
linearTexture: 0
correctGamma: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 0
cubemapConvolution: 0
cubemapConvolutionSteps: 7
cubemapConvolutionExponent: 1.5
seamlessCubemap: 0
textureFormat: -1
maxTextureSize: 2048
textureSettings:
filterMode: 0
aniso: 1
mipBias: -1
wrapMode: 1
nPOTScale: 0
lightmap: 0
rGBM: 0
compressionQuality: 50
allowsAlphaSplitting: 0
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
buildTargetSettings: []
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,41 @@
using UnityEngine;
namespace uDesktopDuplication
{
[AddComponentMenu("uDesktopDuplication/Cursor"),
RequireComponent(typeof(Texture))]
public class Cursor : MonoBehaviour
{
[SerializeField]
Transform cursor;
[SerializeField]
Vector2 modelScale = Vector2.one;
[SerializeField]
Vector2 offset = new Vector2(0.5f, 0.5f);
private Texture texture_;
void OnEnable()
{
texture_ = GetComponent<Texture>();
}
void Update()
{
var monitor = texture_.monitor;
if (monitor.isPointerVisible) {
var x = (1f * monitor.pointerX / monitor.width - 0.5f) * modelScale.x;
var y = (0.5f - 1f * monitor.pointerY / monitor.height) * modelScale.y;
var iy = texture_.invertY ? +1 : -1;
var localPos = transform.right * x + iy * transform.up * y;
var worldPos = transform.TransformPoint(localPos);
worldPos += cursor.right * offset.x * cursor.localScale.x;
worldPos += -cursor.up * offset.y * cursor.localScale.y;
worldPos += -cursor.forward * 0.001f;
cursor.position = worldPos;
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: d2d9e4ca459ecb44da8815bafe9655c5
timeCreated: 1477635630
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 89616e59e1cccb346bd4e959257990ca, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,41 @@
using System;
using System.Text;
using System.Runtime.InteropServices;
namespace uDesktopDuplication
{
public static class Lib
{
[DllImport("uDesktopDuplication")]
public static extern int GetMonitorCount();
[DllImport("uDesktopDuplication")]
public static extern void SetTimeout(int timeout);
[DllImport("uDesktopDuplication")]
public static extern IntPtr GetRenderEventFunc();
[DllImport("uDesktopDuplication")]
public static extern void GetName(int id, StringBuilder buf, int len);
[DllImport("uDesktopDuplication")]
public static extern int GetWidth(int id);
[DllImport("uDesktopDuplication")]
public static extern int GetHeight(int id);
[DllImport("uDesktopDuplication")]
public static extern bool IsPrimary(int id);
[DllImport("uDesktopDuplication")]
public static extern bool IsPointerVisible(int id);
[DllImport("uDesktopDuplication")]
public static extern int GetPointerX(int id);
[DllImport("uDesktopDuplication")]
public static extern int GetPointerY(int id);
[DllImport("uDesktopDuplication")]
public static extern int SetTexturePtr(int id, IntPtr ptr);
public static string GetName(int id)
{
var buf = new StringBuilder(32);
GetName(id, buf, buf.Capacity);
return buf.ToString();
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: cb02196c3e766c14ba398dc130e443e8
timeCreated: 1477643164
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 89616e59e1cccb346bd4e959257990ca, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,85 @@
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
namespace uDesktopDuplication
{
public class Manager : MonoBehaviour
{
private static Manager instance_;
public static Manager instance
{
get
{
if (instance_) return instance_;
var go = new GameObject("uDesktopDuplicationManager");
return go.AddComponent<Manager>();
}
}
private List<Monitor> monitors_ = new List<Monitor>();
static public List<Monitor> monitors
{
get { return instance.monitors_; }
}
static public int monitorCount
{
get { return instance.monitors_.Count; }
}
static public Monitor primary
{
get
{
return instance.monitors_.Find(monitor => monitor.isPrimary);
}
}
[SerializeField, Tooltip("Set Desktop Duplication API timeout (milliseconds).")]
int timeout = 0;
private Coroutine renderCoroutine_ = null;
void Awake()
{
if (instance_ != null) return;
instance_ = this;
for (int i = 0; i < Lib.GetMonitorCount(); ++i) {
monitors.Add(new Monitor(i));
}
Lib.SetTimeout(timeout);
}
void OnEnable()
{
renderCoroutine_ = StartCoroutine(OnRender());
}
void OnDisable()
{
if (renderCoroutine_ != null) {
StopCoroutine(renderCoroutine_);
renderCoroutine_ = null;
}
}
IEnumerator OnRender()
{
for (;;) {
yield return new WaitForEndOfFrame();
for (int i = 0; i < monitors.Count; ++i) {
var monitor = monitors[i];
if (monitor.shouldBeUpdated) {
monitor.Render();
}
monitor.shouldBeUpdated = false;
}
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 4dccb434f55ebee4f91bfb9935092bbf
timeCreated: 1477643174
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 89616e59e1cccb346bd4e959257990ca, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,79 @@
using UnityEngine;
namespace uDesktopDuplication
{
public class Monitor
{
public Monitor(int id)
{
this.id = id;
}
public int id
{
get;
private set;
}
public string name
{
get { return Lib.GetName(id); }
}
public bool isPrimary
{
get { return Lib.IsPrimary(id); }
}
public int width
{
get { return Lib.GetWidth(id); }
}
public int height
{
get { return Lib.GetHeight(id); }
}
public bool isPointerVisible
{
get { return Lib.IsPointerVisible(id); }
}
public int pointerX
{
get { return Lib.GetPointerX(id); }
}
public int pointerY
{
get { return Lib.GetPointerY(id); }
}
public bool shouldBeUpdated
{
get;
set;
}
private Texture2D texture_;
public Texture2D texture
{
get
{
if (texture_ == null) {
texture_ = new Texture2D(width, height, TextureFormat.BGRA32, false);
Lib.SetTexturePtr(id, texture_.GetNativeTexturePtr());
}
return texture_;
}
}
public void Render()
{
GL.IssuePluginEvent(Lib.GetRenderEventFunc(), id);
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 310590b113d909b43b4ea19702904ac3
timeCreated: 1477643181
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 89616e59e1cccb346bd4e959257990ca, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,61 @@
using UnityEngine;
namespace uDesktopDuplication
{
[AddComponentMenu("uDesktopDuplication/Texture")]
public class Texture : MonoBehaviour
{
private Monitor monitor_;
public Monitor monitor
{
get { return monitor_; }
set
{
monitor_ = value;
material_ = GetComponent<Renderer>().material;
material_.mainTexture = monitor_.texture;
}
}
public int monitorId
{
get { return monitor.id; }
set { monitor = Manager.monitors[Mathf.Clamp(value, 0, Manager.monitorCount - 1)]; }
}
public bool invertX = false;
public bool invertY = false;
private Material material_;
void OnEnable()
{
if (monitor == null) {
monitor = Manager.primary;
}
}
void Update()
{
monitor.shouldBeUpdated = true;
UpdateMaterial();
}
void UpdateMaterial()
{
if (invertX) {
material_.EnableKeyword("INVERT_X");
} else {
material_.DisableKeyword("INVERT_X");
}
if (invertY) {
material_.EnableKeyword("INVERT_Y");
} else {
material_.DisableKeyword("INVERT_Y");
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: bb54a34570e4747429b1c5b66c69d356
timeCreated: 1477635636
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 89616e59e1cccb346bd4e959257990ca, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,62 +0,0 @@
using UnityEngine;
using System;
using System.Collections;
using System.Runtime.InteropServices;
public class uDesktopDuplication : MonoBehaviour
{
[DllImport("uDesktopDuplication")]
private static extern void Initialize();
[DllImport("uDesktopDuplication")]
private static extern int GetWidth();
[DllImport("uDesktopDuplication")]
private static extern int GetHeight();
[DllImport("uDesktopDuplication")]
private static extern bool IsPointerVisible();
[DllImport("uDesktopDuplication")]
private static extern int GetPointerX();
[DllImport("uDesktopDuplication")]
private static extern int GetPointerY();
[DllImport("uDesktopDuplication")]
private static extern int SetTexturePtr(IntPtr ptr);
[DllImport("uDesktopDuplication")]
private static extern IntPtr GetRenderEventFunc();
public bool isPointerVisible = false;
public int pointerX = 0;
public int pointerY = 0;
Coroutine renderCoroutine_ = null;
void OnEnable()
{
var tex = new Texture2D(GetWidth(), GetHeight(), TextureFormat.BGRA32, false);
GetComponent<Renderer>().sharedMaterial.mainTexture = tex;
SetTexturePtr(tex.GetNativeTexturePtr());
renderCoroutine_ = StartCoroutine(OnRender());
}
void OnDisable()
{
if (renderCoroutine_ != null) {
StopCoroutine(renderCoroutine_);
renderCoroutine_ = null;
}
}
void Update()
{
isPointerVisible = IsPointerVisible();
pointerX = GetPointerX();
pointerY = GetPointerY();
}
IEnumerator OnRender()
{
for (;;) {
yield return new WaitForEndOfFrame();
GL.IssuePluginEvent(GetRenderEventFunc(), 0);
}
}
}

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 9844af21eb203794b852f0bcaa5f2be2
folderAsset: yes
timeCreated: 1477556975
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,26 @@
#ifndef UDD_COMMON_CGINC
#define UDD_COMMON_CGINC
#include "UnityCG.cginc"
inline void uddInvertUV(inout float2 uv)
{
#ifdef INVERT_X
uv.x *= -1.0;
#endif
#ifdef INVERT_Y
uv.y *= -1.0;
#endif
}
inline fixed4 uddGetTexture(sampler2D tex, float2 uv)
{
uddInvertUV(uv);
fixed4 c = tex2D(tex, uv);
if (!IsGammaSpace()) {
c.rgb = GammaToLinearSpace(c.rgb);
}
return c;
}
#endif

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 1090e048de83c254d99a242f407890c6
timeCreated: 1477561310
licenseType: Pro
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,50 @@
Shader "uDesktopDuplication/Standard"
{
Properties
{
_Color ("Color", Color) = (1, 1, 1, 1)
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_Glossiness ("Smoothness", Range(0, 1)) = 0.5
_Metallic ("Metallic", Range(0, 1)) = 0.0
}
SubShader
{
Tags { "RenderType"="Opaque" }
CGPROGRAM
#pragma target 3.0
#pragma surface surf Standard fullforwardshadows
#pragma multi_compile ___ INVERT_X
#pragma multi_compile ___ INVERT_Y
#include "./uDD_Common.cginc"
sampler2D _MainTex;
struct Input
{
float2 uv_MainTex;
};
half _Glossiness;
half _Metallic;
fixed4 _Color;
void surf(Input IN, inout SurfaceOutputStandard o)
{
fixed4 c = uddGetTexture(_MainTex, IN.uv_MainTex) * _Color;
o.Albedo = c.rgb;
o.Metallic = _Metallic;
o.Smoothness = _Glossiness;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 1428bebbde173ab4ab509941809d6aec
timeCreated: 1477559925
licenseType: Pro
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,65 @@
Shader "uDesktopDuplication/Unlit"
{
Properties
{
_Color ("Color", Color) = (1, 1, 1, 1)
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType"="Opaque" }
CGINCLUDE
#include "UnityCG.cginc"
#include "./uDD_Common.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float4 vertex : SV_POSITION;
float2 uv : TEXCOORD0;
};
sampler2D _MainTex;
float4 _MainTex_ST;
fixed4 _Color;
v2f vert(appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
fixed4 frag(v2f i) : SV_Target
{
return uddGetTexture(_MainTex, i.uv) * _Color;
}
ENDCG
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile ___ INVERT_X
#pragma multi_compile ___ INVERT_Y
ENDCG
}
}
Fallback "Unlit/Texture"
}

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 2ca7b38c676bddd439a77a646a279a54
timeCreated: 1477556963
licenseType: Pro
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,72 @@
Shader "uDesktopDuplication/Unlit BlackMask"
{
Properties
{
_Color ("Color", Color) = (1, 1, 1, 1)
_MainTex ("Texture", 2D) = "white" {}
_Mask ("Mask", Range(0, 1)) = 0.1
}
SubShader
{
Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
CGINCLUDE
#include "UnityCG.cginc"
#include "./uDD_Common.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float4 vertex : SV_POSITION;
float2 uv : TEXCOORD0;
};
sampler2D _MainTex;
float4 _MainTex_ST;
fixed4 _Color;
fixed _Mask;
v2f vert(appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
fixed4 frag(v2f i) : SV_Target
{
fixed4 tex = uddGetTexture(_MainTex, i.uv);
fixed alpha = pow((tex.r + tex.g + tex.b) / 3.0, _Mask);
return fixed4(tex.rgb * _Color.rgb, alpha);
}
ENDCG
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile ___ INVERT_X
#pragma multi_compile ___ INVERT_Y
ENDCG
}
}
Fallback "Unlit/Texture"
}

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 8d8bed8b85c7bb844a44481b2feb53ca
timeCreated: 1477561145
licenseType: Pro
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,68 @@
Shader "uDesktopDuplication/Unlit Transparent"
{
Properties
{
_Color ("Color", Color) = (1, 1, 1, 1)
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
CGINCLUDE
#include "UnityCG.cginc"
#include "./uDD_Common.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float4 vertex : SV_POSITION;
float2 uv : TEXCOORD0;
};
sampler2D _MainTex;
float4 _MainTex_ST;
fixed4 _Color;
v2f vert(appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
fixed4 frag(v2f i) : SV_Target
{
return fixed4(uddGetTexture(_MainTex, i.uv).rgb, 1.0) * _Color;
}
ENDCG
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile ___ INVERT_X
#pragma multi_compile ___ INVERT_Y
ENDCG
}
}
Fallback "Unlit/Transparent"
}

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 32b14c1fb31640f43b002138823eb1e1
timeCreated: 1477560210
licenseType: Pro
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,5 +1,7 @@
#include <d3d11.h>
#include <dxgi1_2.h>
#include <vector>
#include <string>
#include "IUnityInterface.h"
#include "IUnityGraphics.h"
@@ -10,21 +12,40 @@
namespace
{
IUnityInterfaces* g_unity = nullptr;
IDXGIOutputDuplication* g_deskDupl = nullptr;
ID3D11Texture2D* g_texture = nullptr;
bool g_isPointerVisible = -1;
int g_pointerX = -1;
int g_pointerY = -1;
int g_width = -1;
int g_height = -1;
struct Monitor
{
IDXGIOutputDuplication* output = nullptr;
ID3D11Texture2D* texture = nullptr;
std::string name = "";
bool isPrimary = false;
bool isPointerVisible = false;
int pointerX = -1;
int pointerY = -1;
int width = -1;
int height = -1;
};
IUnityInterfaces* g_unity = nullptr;
int g_timeout = 10;
std::vector<Monitor> g_monitors;
}
extern "C"
{
void FinalizeDuplication()
{
for (auto& monitor : g_monitors)
{
monitor.output->Release();
}
g_monitors.clear();
}
void InitializeDuplication()
{
FinalizeDuplication();
IDXGIFactory1* factory;
CreateDXGIFactory1(__uuidof(IDXGIFactory1), reinterpret_cast<void**>(&factory));
@@ -34,7 +55,7 @@ extern "C"
{
// Search the main monitor from all outputs.
IDXGIOutput* output;
for (int j = 0; (adapter->EnumOutputs(j, &output) != DXGI_ERROR_NOT_FOUND); j++)
for (int j = 0; (adapter->EnumOutputs(j, &output) != DXGI_ERROR_NOT_FOUND); ++j)
{
DXGI_OUTPUT_DESC outputDesc;
output->GetDesc(&outputDesc);
@@ -43,22 +64,18 @@ extern "C"
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;
Monitor monitor;
monitor.name = monitorInfo.szDevice;
monitor.isPrimary = (monitorInfo.dwFlags == MONITORINFOF_PRIMARY);
monitor.width = monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left;
monitor.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);
auto device = g_unity->Get<IUnityGraphicsD3D11>()->GetDevice();
IDXGIOutput1* output1;
output1 = reinterpret_cast<IDXGIOutput1*>(output);
output1->DuplicateOutput(device, &monitor.output);
output->Release();
adapter->Release();
factory->Release();
return;
}
g_monitors.push_back(monitor);
output->Release();
}
@@ -69,12 +86,6 @@ extern "C"
factory->Release();
}
void FinalizeDuplication()
{
g_deskDupl->Release();
g_deskDupl = nullptr;
}
UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API UnityPluginLoad(IUnityInterfaces* unityInterfaces)
{
g_unity = unityInterfaces;
@@ -84,24 +95,26 @@ extern "C"
UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API UnityPluginUnload()
{
g_unity = nullptr;
g_texture = nullptr;
g_width = -1;
g_height = -1;
g_pointerX = -1;
g_pointerY = -1;
FinalizeDuplication();
}
void UNITY_INTERFACE_API OnRenderEvent(int eventId)
bool DoesMonitorExist(int id)
{
if (g_deskDupl == nullptr || g_texture == nullptr) return;
return id >= 0 && id < g_monitors.size();
}
void UNITY_INTERFACE_API OnRenderEvent(int id)
{
if (!DoesMonitorExist(id)) return;
auto& monitor = g_monitors[id];
if (monitor.output == nullptr || monitor.texture == nullptr) return;
HRESULT hr;
IDXGIResource* resource = nullptr;
DXGI_OUTDUPL_FRAME_INFO frameInfo;
const UINT timeout = 100; // ms
hr = g_deskDupl->AcquireNextFrame(timeout, &frameInfo, &resource);
hr = monitor.output->AcquireNextFrame(g_timeout, &frameInfo, &resource);
switch (hr)
{
case S_OK:
@@ -110,7 +123,7 @@ extern "C"
}
case DXGI_ERROR_ACCESS_LOST:
{
FinalizeDuplication();
resource->Release();
InitializeDuplication();
return;
}
@@ -120,26 +133,27 @@ extern "C"
}
}
g_isPointerVisible = frameInfo.PointerPosition.Visible;
g_pointerX = frameInfo.PointerPosition.Position.x;
g_pointerY = frameInfo.PointerPosition.Position.y;
monitor.isPointerVisible = frameInfo.PointerPosition.Visible == TRUE;
monitor.pointerX = frameInfo.PointerPosition.Position.x;
monitor.pointerY = frameInfo.PointerPosition.Position.y;
ID3D11Texture2D* texture;
hr = resource->QueryInterface(__uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&texture));
if (hr != S_OK)
{
resource->Release();
monitor.output->ReleaseFrame();
return;
}
resource->Release();
ID3D11DeviceContext* context;
auto device = g_unity->Get<IUnityGraphicsD3D11>()->GetDevice();
device->GetImmediateContext(&context);
context->CopyResource(g_texture, texture);
context->CopyResource(monitor.texture, texture);
g_deskDupl->ReleaseFrame();
resource->Release();
texture->Release();
monitor.output->ReleaseFrame();
}
UNITY_INTERFACE_EXPORT UnityRenderingEvent UNITY_INTERFACE_API GetRenderEventFunc()
@@ -147,33 +161,61 @@ extern "C"
return OnRenderEvent;
}
UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API GetWidth()
UNITY_INTERFACE_EXPORT size_t UNITY_INTERFACE_API GetMonitorCount()
{
return g_width;
return g_monitors.size();
}
UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API GetHeight()
UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API SetTimeout(int timeout)
{
return g_height;
g_timeout = timeout;
}
UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API IsPointerVisible()
UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API GetName(int id, char* buf, int len)
{
return g_isPointerVisible;
if (!DoesMonitorExist(id)) return;
strcpy_s(buf, len, g_monitors[id].name.c_str());
}
UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API GetPointerX()
UNITY_INTERFACE_EXPORT bool UNITY_INTERFACE_API IsPrimary(int id)
{
return g_pointerX;
if (!DoesMonitorExist(id)) return false;
return g_monitors[id].isPrimary;
}
UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API GetPointerY()
UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API GetWidth(int id)
{
return g_pointerY;
if (!DoesMonitorExist(id)) return -1;
return g_monitors[id].width;
}
UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API SetTexturePtr(void* texture)
UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API GetHeight(int id)
{
g_texture = reinterpret_cast<ID3D11Texture2D*>(texture);
if (!DoesMonitorExist(id)) return -1;
return g_monitors[id].height;
}
UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API IsPointerVisible(int id)
{
if (!DoesMonitorExist(id)) return false;
return g_monitors[id].isPointerVisible;
}
UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API GetPointerX(int id)
{
if (!DoesMonitorExist(id)) return -1;
return g_monitors[id].pointerX;
}
UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API GetPointerY(int id)
{
if (!DoesMonitorExist(id)) return -1;
return g_monitors[id].pointerY;
}
UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API SetTexturePtr(int id, void* texture)
{
if (!DoesMonitorExist(id)) return;
g_monitors[id].texture = reinterpret_cast<ID3D11Texture2D*>(texture);
}
}

View File

@@ -1,12 +1,12 @@
uDesktopDuplication
===================
**uDesktopDuplication** is Desktop Duplication API implementation for Unity.
**uDesktopDuplication** is a Unity asset to use the realtime screen capture as `Texture2D` using Desktop Duplication API.
ScreenShot
----------
![uDesktopDuplication](https://raw.githubusercontent.com/wiki/hecomi/uDesktopDuplication/screenshot.png)
![uDesktopDuplication](https://raw.githubusercontent.com/wiki/hecomi/uDesktopDuplication/animation.gif)
Environment
@@ -22,20 +22,38 @@ Please download the latest *uDesktopDuplication.unitypackage* from the [release
Usage
-----
Attach `uDesktopDuplication.cs` component to the target object, then its main texture will be replaced with the captured screen.
TODOs
-----
- [ ] Mouse cursor
- [ ] Monitor selector
- [ ] Support linear color
Please request new features you want to issues.
Attach `uDesktopDuplication/Texture` component to the target object, then its main texture will be replaced with the captured screen. Please see example scenes for more details.
Version
-------
| Data | Version | Description |
| ---------- | ------- | --------------------------- |
| 2016/10/27 | 0.0.1 | Initial commit. |
| Data | Version | Description |
| ---------- | ------- | --------------------------------- |
| 2016/10/28 | 1.0.0 | Support multiple screens. |
| 2016/10/27 | 0.0.3 | Support lienar color. |
| 2016/10/27 | 0.0.2 | Add mouse cursor / shaders. |
| 2016/10/27 | 0.0.1 | Initial commit. |
Lisence
-------
The MIT License (MIT)
Copyright (c) 2016 hecomi
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.