add clipping function and the example.

This commit is contained in:
hecomi
2016-11-06 23:28:33 +09:00
parent 8e2d8d3218
commit 33a55d95bd
19 changed files with 155 additions and 36 deletions
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f3d41026babadc241b9d0852b0831584
timeCreated: 1478436298
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,37 @@
using UnityEngine;
public class Loupe : MonoBehaviour
{
private uDesktopDuplication.Texture uddTexture_;
public float zoom = 3f;
public float aspect = 1f;
void Start()
{
uddTexture_ = GetComponent<uDesktopDuplication.Texture>();
uddTexture_.useClip = true;
}
void Update()
{
// To get other monitor textures, set dirty flag.
foreach (var monitor in uDesktopDuplication.Manager.monitors) {
monitor.CreateTexture();
monitor.shouldBeUpdated = true;
}
if (!uddTexture_.monitor.isCursorVisible) {
uddTexture_.monitorId = uDesktopDuplication.Manager.cursorMonitorId;
}
var x = (float)uddTexture_.monitor.cursorX / uddTexture_.monitor.width;
var y = (float)uddTexture_.monitor.cursorY / uddTexture_.monitor.height;
var w = 1f / zoom;
var h = w / aspect * uddTexture_.monitor.aspect;
x = Mathf.Clamp(x - w / 2, 0f, 1f - w);
y = Mathf.Clamp(y - h / 2, 0f, 1f - h);
uddTexture_.clipPos = new Vector2(x, y);
uddTexture_.clipScale = new Vector2(w, h);
}
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: efd9499cdb931b945947a2cd47909676
timeCreated: 1478438457
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+2 -3
View File
@@ -60,9 +60,8 @@ public class Cursor : MonoBehaviour
void UpdateMaterial() void UpdateMaterial()
{ {
bool isVisible = monitor.isCursorVisible; var x = monitor.isCursorVisible ? (float)monitor.cursorX / monitor.width : -9999f;
var x = isVisible ? (float)monitor.cursorX / monitor.width : -9999f; var y = monitor.isCursorVisible ? (float)monitor.cursorY / monitor.height : -9999f;
var y = isVisible ? (float)monitor.cursorY / monitor.height : -9999f;
var w = (float)monitor.cursorShapeWidth / monitor.width; var w = (float)monitor.cursorShapeWidth / monitor.width;
var h = (float)monitor.cursorShapeHeight / monitor.height; var h = (float)monitor.cursorShapeHeight / monitor.height;
uddTexture_.material.SetVector("_CursorPositionScale", new Vector4(x, y, w, h)); uddTexture_.material.SetVector("_CursorPositionScale", new Vector4(x, y, w, h));
@@ -56,6 +56,8 @@ public static class Lib
[DllImport("uDesktopDuplication")] [DllImport("uDesktopDuplication")]
public static extern int GetMonitorCount(); public static extern int GetMonitorCount();
[DllImport("uDesktopDuplication")] [DllImport("uDesktopDuplication")]
public static extern int GetCursorMonitorId();
[DllImport("uDesktopDuplication")]
public static extern int GetTotalWidth(); public static extern int GetTotalWidth();
[DllImport("uDesktopDuplication")] [DllImport("uDesktopDuplication")]
public static extern int GetTotalHeight(); public static extern int GetTotalHeight();
@@ -38,6 +38,11 @@ public class Manager : MonoBehaviour
get { return Lib.GetMonitorCount(); } get { return Lib.GetMonitorCount(); }
} }
static public int cursorMonitorId
{
get { return Lib.GetCursorMonitorId(); }
}
static public Monitor primary static public Monitor primary
{ {
get get
@@ -196,7 +196,7 @@ public class Monitor
Lib.GetCursorTexture(id, ptr); Lib.GetCursorTexture(id, ptr);
} }
void CreateTexture() public void CreateTexture()
{ {
if (!available) return; if (!available) return;
@@ -24,9 +24,15 @@ public class Texture : MonoBehaviour
set { monitor = Manager.monitors[Mathf.Clamp(value, 0, Manager.monitorCount - 1)]; } set { monitor = Manager.monitors[Mathf.Clamp(value, 0, Manager.monitorCount - 1)]; }
} }
[Header("Invert UVs")]
public bool invertX = false; public bool invertX = false;
public bool invertY = false; public bool invertY = false;
[Header("Clip")]
public bool useClip = false;
public Vector2 clipPos = Vector2.zero;
public Vector2 clipScale = new Vector2(0.2f, 0.2f);
public Material material public Material material
{ {
get; get;
@@ -55,6 +61,13 @@ public class Texture : MonoBehaviour
} }
void UpdateMaterial() void UpdateMaterial()
{
Invert();
Rotate();
Clip();
}
void Invert()
{ {
if (invertX) { if (invertX) {
material.EnableKeyword("INVERT_X"); material.EnableKeyword("INVERT_X");
@@ -67,7 +80,10 @@ public class Texture : MonoBehaviour
} else { } else {
material.DisableKeyword("INVERT_Y"); material.DisableKeyword("INVERT_Y");
} }
}
void Rotate()
{
switch (monitor.rotation) switch (monitor.rotation)
{ {
case MonitorRotation.Identity: case MonitorRotation.Identity:
@@ -94,6 +110,16 @@ public class Texture : MonoBehaviour
break; break;
} }
} }
void Clip()
{
if (useClip) {
material.EnableKeyword("USE_CLIP");
material.SetVector("_ClipPositionScale", new Vector4(clipPos.x, clipPos.y, clipScale.x, clipScale.y));
} else {
material.DisableKeyword("USE_CLIP");
}
}
} }
} }
@@ -2,6 +2,7 @@
#define UDD_COMMON_CGINC #define UDD_COMMON_CGINC
#include "UnityCG.cginc" #include "UnityCG.cginc"
#include "./uDD_Params.cginc"
struct appdata struct appdata
{ {
@@ -48,6 +49,13 @@ float2 uddRotateUV(float2 uv)
return uv; return uv;
} }
float2 uddClipUV(float2 uv)
{
uv.x = _ClipX + uv.x * _ClipWidth;
uv.y = _ClipY + uv.y * _ClipHeight;
return uv;
}
inline void uddConvertToLinearIfNeeded(inout fixed3 rgb) inline void uddConvertToLinearIfNeeded(inout fixed3 rgb)
{ {
if (!IsGammaSpace()) { if (!IsGammaSpace()) {
@@ -55,27 +63,30 @@ inline void uddConvertToLinearIfNeeded(inout fixed3 rgb)
} }
} }
inline fixed4 uddGetScreenTexture(sampler2D tex, float2 uv) inline fixed4 uddGetScreenTexture(float2 uv)
{ {
fixed4 c = tex2D(tex, uv); fixed4 c = tex2D(_MainTex, uv);
return c; return c;
} }
inline fixed4 uddGetCursorTexture(sampler2D tex, float2 uv, fixed4 cursorPosScale) inline fixed4 uddGetCursorTexture(float2 uv)
{ {
uv.x = (uv.x - cursorPosScale.x) / cursorPosScale.z; uv.x = (uv.x - _CursorX) / _CursorWidth;
uv.y = (uv.y - cursorPosScale.y) / cursorPosScale.w; uv.y = (uv.y - _CursorY) / _CursorHeight;
fixed4 c = tex2D(tex, uv); fixed4 c = tex2D(_CursorTex, uv);
fixed a = c.a * step(0, uv.x) * step(0, uv.y) * step(uv.x, 1) * step(uv.y, 1); fixed a = c.a * step(0, uv.x) * step(0, uv.y) * step(uv.x, 1) * step(uv.y, 1);
c *= step(0.01, a); c *= step(0.01, a);
return c; return c;
} }
inline fixed4 uddGetScreenTextureWithCursor(sampler2D screenTex, sampler2D cursorTex, float2 uv, fixed4 cursorPosScale) inline fixed4 uddGetScreenTextureWithCursor(float2 uv)
{ {
uv = uddInvertUV(uv); uv = uddInvertUV(uv);
fixed4 screen = uddGetScreenTexture(screenTex, uddRotateUV(uv)); #ifdef USE_CLIP
fixed4 cursor = uddGetCursorTexture(cursorTex, uv, cursorPosScale); uv = uddClipUV(uv);
#endif
fixed4 screen = uddGetScreenTexture(uddRotateUV(uv));
fixed4 cursor = uddGetCursorTexture(uv);
fixed4 color = lerp(screen, cursor, cursor.a); fixed4 color = lerp(screen, cursor, cursor.a);
uddConvertToLinearIfNeeded(color.rgb); uddConvertToLinearIfNeeded(color.rgb);
return color; return color;
@@ -4,7 +4,18 @@
sampler2D _MainTex; sampler2D _MainTex;
fixed4 _Color; fixed4 _Color;
sampler2D _CursorTex; sampler2D _CursorTex;
half4 _CursorPositionScale; half4 _CursorPositionScale;
#define _CursorX _CursorPositionScale.x
#define _CursorY _CursorPositionScale.y
#define _CursorWidth _CursorPositionScale.z
#define _CursorHeight _CursorPositionScale.w
half4 _ClipPositionScale;
#define _ClipX _ClipPositionScale.x
#define _ClipY _ClipPositionScale.y
#define _ClipWidth _ClipPositionScale.z
#define _ClipHeight _ClipPositionScale.w
#ifndef SURFACE_SHADER #ifndef SURFACE_SHADER
float4 _MainTex_ST; float4 _MainTex_ST;
@@ -22,19 +22,19 @@ SubShader
#pragma surface surf Standard fullforwardshadows #pragma surface surf Standard fullforwardshadows
#pragma multi_compile ___ INVERT_X #pragma multi_compile ___ INVERT_X
#pragma multi_compile ___ INVERT_Y #pragma multi_compile ___ INVERT_Y
#pragma multi_compile ___ VERTICAL
#pragma multi_compile ___ ROTATE90 ROTATE180 ROTATE270 #pragma multi_compile ___ ROTATE90 ROTATE180 ROTATE270
#pragma multi_compile ___ USE_BEND
#pragma multi_compile ___ USE_CLIP
#define SURFACE_SHADER #define SURFACE_SHADER
#include "./uDD_Common.cginc" #include "./uDD_Common.cginc"
#include "./uDD_Params.cginc"
half _Glossiness; half _Glossiness;
half _Metallic; half _Metallic;
void surf(Input IN, inout SurfaceOutputStandard o) void surf(Input IN, inout SurfaceOutputStandard o)
{ {
fixed4 c = uddGetScreenTextureWithCursor(_MainTex, _CursorTex, IN.uv_MainTex, _CursorPositionScale) * _Color; fixed4 c = uddGetScreenTextureWithCursor(IN.uv_MainTex) * _Color;
o.Albedo = c.rgb; o.Albedo = c.rgb;
o.Metallic = _Metallic; o.Metallic = _Metallic;
o.Smoothness = _Glossiness; o.Smoothness = _Glossiness;
@@ -20,7 +20,6 @@ Cull [_Cull]
CGINCLUDE CGINCLUDE
#include "./uDD_Common.cginc" #include "./uDD_Common.cginc"
#include "./uDD_Params.cginc"
fixed _Radius; fixed _Radius;
@@ -39,7 +38,7 @@ v2f vert(appdata v)
fixed4 frag(v2f i) : SV_Target fixed4 frag(v2f i) : SV_Target
{ {
return uddGetScreenTextureWithCursor(_MainTex, _CursorTex, i.uv, _CursorPositionScale); return uddGetScreenTextureWithCursor(i.uv);
} }
ENDCG ENDCG
@@ -51,9 +50,9 @@ Pass
#pragma fragment frag #pragma fragment frag
#pragma multi_compile ___ INVERT_X #pragma multi_compile ___ INVERT_X
#pragma multi_compile ___ INVERT_Y #pragma multi_compile ___ INVERT_Y
#pragma multi_compile ___ VERTICAL
#pragma shader_feature ___ USE_BEND
#pragma multi_compile ___ ROTATE90 ROTATE180 ROTATE270 #pragma multi_compile ___ ROTATE90 ROTATE180 ROTATE270
#pragma multi_compile ___ USE_BEND
#pragma multi_compile ___ USE_CLIP
ENDCG ENDCG
} }
@@ -21,7 +21,6 @@ Blend SrcAlpha OneMinusSrcAlpha
CGINCLUDE CGINCLUDE
#include "./uDD_Common.cginc" #include "./uDD_Common.cginc"
#include "./uDD_Params.cginc"
fixed _Mask; fixed _Mask;
@@ -35,7 +34,7 @@ v2f vert(appdata v)
fixed4 frag(v2f i) : SV_Target fixed4 frag(v2f i) : SV_Target
{ {
fixed4 tex = uddGetScreenTextureWithCursor(_MainTex, _CursorTex, i.uv, _CursorPositionScale); fixed4 tex = uddGetScreenTextureWithCursor(i.uv);
fixed alpha = pow((tex.r + tex.g + tex.b) / 3.0, _Mask); fixed alpha = pow((tex.r + tex.g + tex.b) / 3.0, _Mask);
return fixed4(tex.rgb * _Color.rgb, alpha * _Color.a); return fixed4(tex.rgb * _Color.rgb, alpha * _Color.a);
} }
@@ -49,8 +48,9 @@ Pass
#pragma fragment frag #pragma fragment frag
#pragma multi_compile ___ INVERT_X #pragma multi_compile ___ INVERT_X
#pragma multi_compile ___ INVERT_Y #pragma multi_compile ___ INVERT_Y
#pragma multi_compile ___ VERTICAL
#pragma multi_compile ___ ROTATE90 ROTATE180 ROTATE270 #pragma multi_compile ___ ROTATE90 ROTATE180 ROTATE270
#pragma multi_compile ___ USE_BEND
#pragma multi_compile ___ USE_CLIP
ENDCG ENDCG
} }
@@ -20,7 +20,6 @@ Blend SrcAlpha OneMinusSrcAlpha
CGINCLUDE CGINCLUDE
#include "./uDD_Common.cginc" #include "./uDD_Common.cginc"
#include "./uDD_Params.cginc"
v2f vert(appdata v) v2f vert(appdata v)
{ {
@@ -32,7 +31,7 @@ v2f vert(appdata v)
fixed4 frag(v2f i) : SV_Target fixed4 frag(v2f i) : SV_Target
{ {
return fixed4(uddGetScreenTextureWithCursor(_MainTex, _CursorTex, i.uv, _CursorPositionScale).rgb, 1.0) * _Color; return fixed4(uddGetScreenTextureWithCursor(i.uv).rgb, 1.0) * _Color;
} }
ENDCG ENDCG
@@ -44,8 +43,9 @@ Pass
#pragma fragment frag #pragma fragment frag
#pragma multi_compile ___ INVERT_X #pragma multi_compile ___ INVERT_X
#pragma multi_compile ___ INVERT_Y #pragma multi_compile ___ INVERT_Y
#pragma multi_compile ___ VERTICAL
#pragma multi_compile ___ ROTATE90 ROTATE180 ROTATE270 #pragma multi_compile ___ ROTATE90 ROTATE180 ROTATE270
#pragma multi_compile ___ USE_BEND
#pragma multi_compile ___ USE_CLIP
ENDCG ENDCG
} }
@@ -38,7 +38,8 @@ void Cursor::UpdateBuffer(const DXGI_OUTDUPL_FRAME_INFO& frameInfo)
isVisible_ = frameInfo.PointerPosition.Visible != 0; isVisible_ = frameInfo.PointerPosition.Visible != 0;
timestamp_ = frameInfo.LastMouseUpdateTime; timestamp_ = frameInfo.LastMouseUpdateTime;
if (frameInfo.PointerPosition.Visible != 0) { if (isVisible_)
{
GetMonitorManager()->SetCursorMonitorId(monitor_->GetId()); GetMonitorManager()->SetCursorMonitorId(monitor_->GetId());
} }
@@ -72,8 +72,6 @@ HRESULT Monitor::Render(UINT timeout)
return S_OK; return S_OK;
} }
if (unityTexture_ == nullptr) return 0;
IDXGIResource* resource = nullptr; IDXGIResource* resource = nullptr;
DXGI_OUTDUPL_FRAME_INFO frameInfo; DXGI_OUTDUPL_FRAME_INFO frameInfo;
@@ -97,18 +95,22 @@ HRESULT Monitor::Render(UINT timeout)
return hr; return hr;
} }
ID3D11Texture2D* texture; if (unityTexture_)
resource->QueryInterface(__uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&texture)); {
ID3D11Texture2D* texture;
resource->QueryInterface(__uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&texture));
ID3D11DeviceContext* context; ID3D11DeviceContext* context;
GetDevice()->GetImmediateContext(&context); GetDevice()->GetImmediateContext(&context);
context->CopyResource(unityTexture_, texture); context->CopyResource(unityTexture_, texture);
context->Release(); context->Release();
resource->Release();
}
cursor_->UpdateBuffer(frameInfo); cursor_->UpdateBuffer(frameInfo);
cursor_->UpdateTexture(); cursor_->UpdateTexture();
resource->Release();
deskDupl_->ReleaseFrame(); deskDupl_->ReleaseFrame();
return S_OK; return S_OK;
@@ -118,6 +118,12 @@ extern "C"
return g_manager->GetMonitorCount(); return g_manager->GetMonitorCount();
} }
UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API GetCursorMonitorId()
{
if (!g_manager) return -1;
return g_manager->GetCursorMonitorId();
}
UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API GetTotalWidth() UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API GetTotalWidth()
{ {
if (!g_manager) return 0; if (!g_manager) return 0;