Skip to content

Commit 46db696

Browse files
committed
Add Compute Shader by Pema:
- Add compute shader to offload the expensive bounding box finder - The compute shader was created by Pema Malling! ( https://github.com/pema99/ ) - Add shader to just draw the highlight using an input rectangle - Add Compute Shader toggle (default on)
1 parent 214706e commit 46db696

8 files changed

Lines changed: 215 additions & 3 deletions
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
Copyright 2022 Pema Malling
3+
4+
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:
5+
6+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
7+
8+
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.
9+
*/
10+
11+
using System.Linq;
12+
using UnityEditor;
13+
using UnityEngine;
14+
15+
namespace Hai.BlendshapeViewer.Scripts.Editor
16+
{
17+
public class BlendshapeViewerDiffCompute
18+
{
19+
private readonly ComputeShader _computeShader;
20+
21+
public BlendshapeViewerDiffCompute()
22+
{
23+
_computeShader = FindComputeShader();
24+
}
25+
26+
public Vector4 Compute(Texture2D textureA, Texture2D textureB)
27+
{
28+
var results = new int[4];
29+
var buf = new ComputeBuffer(4, sizeof(int));
30+
buf.SetData(results);
31+
var computeShader = _computeShader;
32+
33+
var csMain = computeShader.FindKernel("DiffCompute");
34+
35+
computeShader.SetTexture(csMain, "InputA", textureA);
36+
computeShader.SetTexture(csMain, "InputB", textureB);
37+
computeShader.SetBuffer(csMain, "ResultBuffer", buf);
38+
39+
computeShader.Dispatch(csMain, textureA.width / 8, textureB.height / 8, 1);
40+
41+
buf.GetData(results);
42+
return new Vector4(results[0], results[1], results[2], results[3]);
43+
}
44+
45+
private static ComputeShader FindComputeShader()
46+
{
47+
var assetPathOrEmpty = AssetDatabase.GUIDToAssetPath("569e5a4e6b0efc74b93a42db6d069724");
48+
var defaultPath = "Assets/Hai/BlendshapeViewer/Scripts/Editor/DiffCompute.compute";
49+
var computeShader = AssetDatabase.LoadAssetAtPath<ComputeShader>(assetPathOrEmpty == "" ? defaultPath : assetPathOrEmpty)
50+
?? FindAmongAllComputeShaders();
51+
return computeShader;
52+
}
53+
54+
private static ComputeShader FindAmongAllComputeShaders()
55+
{
56+
return Resources.FindObjectsOfTypeAll<ComputeShader>()
57+
.First(o => o.name.Contains("DiffCompute"));
58+
}
59+
}
60+
}

Assets/Hai/BlendshapeViewer/Scripts/Editor/BlendshapeViewerDiffCompute.cs.meta

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Assets/Hai/BlendshapeViewer/Scripts/Editor/BlendshapeViewerEditorWindow.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ public class BlendshapeViewerEditorWindow : EditorWindow
1313
public bool autoUpdateOnFocus = true;
1414
public int thumbnailSize = 100;
1515
public bool showHotspots;
16+
public bool useComputeShader = true;
1617
public Texture2D[] tex2ds = new Texture2D[0];
1718
private Vector2 _scrollPos;
1819
private SkinnedMeshRenderer _generatedFor;
@@ -52,7 +53,13 @@ private void OnGUI()
5253
EditorGUILayout.PropertyField(serializedObject.FindProperty(nameof(showHotspots)));
5354
}
5455
EditorGUILayout.EndHorizontal();
56+
EditorGUILayout.BeginHorizontal();
5557
EditorGUILayout.PropertyField(serializedObject.FindProperty(nameof(autoUpdateOnFocus)));
58+
if (SystemInfo.supportsComputeShaders)
59+
{
60+
EditorGUILayout.PropertyField(serializedObject.FindProperty(nameof(useComputeShader)));
61+
}
62+
EditorGUILayout.EndHorizontal();
5663
EditorGUILayout.IntSlider(serializedObject.FindProperty(nameof(thumbnailSize)), 100, 300);
5764

5865
EditorGUI.BeginDisabledGroup(skinnedMesh == null || AnimationMode.InAnimationMode());
@@ -156,7 +163,7 @@ private void Generate()
156163
var module = new BlendshapeViewerGenerator();
157164
try
158165
{
159-
module.Begin(skinnedMesh, showHotspots ? 0.95f : 0);
166+
module.Begin(skinnedMesh, showHotspots ? 0.95f : 0, useComputeShader);
160167
Texture2D neutralTexture = null;
161168
if (showDifferences)
162169
{

Assets/Hai/BlendshapeViewer/Scripts/Editor/BlendshapeViewerGenerator.cs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,18 @@ public class BlendshapeViewerGenerator
77
{
88
private Material _material;
99
private SkinnedMeshRenderer _skinnedMesh;
10+
private bool _useComputeShader;
1011
private Camera _camera;
1112
private float _overlay;
13+
private BlendshapeViewerDiffCompute _diffCompute;
1214

13-
public void Begin(SkinnedMeshRenderer skinnedMesh, float overlay)
15+
public void Begin(SkinnedMeshRenderer skinnedMesh, float overlay, bool useComputeShader)
1416
{
1517
_skinnedMesh = skinnedMesh;
1618
_overlay = overlay;
17-
_material = new Material(Shader.Find("Hai/BlendshapeViewer"));
19+
_useComputeShader = SystemInfo.supportsComputeShaders && useComputeShader;
20+
21+
_material = new Material(_useComputeShader ? Shader.Find("Hai/BlendshapeViewerRectOnly") : Shader.Find("Hai/BlendshapeViewer"));
1822
_material.SetFloat("_Hotspots", _overlay);
1923
_camera = new GameObject().AddComponent<Camera>();
2024

@@ -27,6 +31,11 @@ public void Begin(SkinnedMeshRenderer skinnedMesh, float overlay)
2731
_camera.nearClipPlane = sceneCamera.nearClipPlane;
2832
_camera.farClipPlane = sceneCamera.farClipPlane;
2933
_camera.orthographicSize = sceneCamera.orthographicSize;
34+
35+
if (_useComputeShader)
36+
{
37+
_diffCompute = new BlendshapeViewerDiffCompute();
38+
}
3039
}
3140

3241
public void Terminate()
@@ -86,6 +95,10 @@ public void Diff(Texture2D source, Texture2D neutralTexture, Texture2D newTextur
8695
{
8796
var diff = RenderTexture.GetTemporary(newTexture.width, newTexture.height, 24);
8897
_material.SetTexture("_NeutralTex", neutralTexture);
98+
if (_useComputeShader)
99+
{
100+
_material.SetVector("_Rect", _diffCompute.Compute(source, neutralTexture));
101+
}
89102
Graphics.Blit(source, diff, _material);
90103
RenderTextureTo(diff, newTexture);
91104
RenderTexture.ReleaseTemporary(diff);
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
Copyright 2022 Pema Malling
3+
4+
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:
5+
6+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
7+
8+
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.
9+
*/
10+
11+
#pragma kernel DiffCompute
12+
13+
Texture2D<float4> InputA;
14+
Texture2D<float4> InputB;
15+
RWStructuredBuffer<int> ResultBuffer; // [minX, minY, maxX, maxY]
16+
17+
[numthreads(8,8,1)]
18+
void DiffCompute (uint3 id : SV_DispatchThreadID)
19+
{
20+
float3 diff = InputA[id.xy].xyz - InputB[id.xy].xyz;
21+
if (dot(diff, diff) > 0.01)
22+
{
23+
// handle first occurrence, this branch needs to be here because stupid compiler
24+
if (ResultBuffer[0] == 0)
25+
{
26+
InterlockedCompareStore(ResultBuffer[0], 0, id.x);
27+
InterlockedCompareStore(ResultBuffer[1], 0, id.y);
28+
InterlockedCompareStore(ResultBuffer[2], 0, id.x);
29+
InterlockedCompareStore(ResultBuffer[3], 0, id.y);
30+
}
31+
32+
// calc AABB points
33+
{
34+
InterlockedMin(ResultBuffer[0], id.x);
35+
InterlockedMin(ResultBuffer[1], id.y);
36+
InterlockedMax(ResultBuffer[2], id.x);
37+
InterlockedMax(ResultBuffer[3], id.y);
38+
}
39+
}
40+
}

Assets/Hai/BlendshapeViewer/Scripts/Editor/DiffCompute.compute.meta

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
Shader "Hai/BlendshapeViewerRectOnly"
2+
{
3+
Properties
4+
{
5+
_MainTex ("Morphed Texture", 2D) = "white" {}
6+
_NeutralTex ("Neutral Texture", 2D) = "white" {}
7+
_Hotspots ("Hotspots", Range(0, 1)) = 0
8+
_Rect ("Rect", Vector) = (0, 0, 0, 0)
9+
}
10+
SubShader
11+
{
12+
Tags { "RenderType"="Opaque" }
13+
LOD 100
14+
15+
Pass
16+
{
17+
CGPROGRAM
18+
#pragma vertex vert
19+
#pragma fragment frag
20+
21+
#include "UnityCG.cginc"
22+
23+
struct appdata
24+
{
25+
float4 vertex : POSITION;
26+
float2 uv : TEXCOORD0;
27+
};
28+
29+
struct v2f
30+
{
31+
float2 uv : TEXCOORD0;
32+
UNITY_FOG_COORDS(1)
33+
float4 vertex : SV_POSITION;
34+
};
35+
36+
sampler2D _MainTex;
37+
float4 _MainTex_ST;
38+
float4 _MainTex_TexelSize;
39+
40+
sampler2D _NeutralTex;
41+
float4 _NeutralTex_ST;
42+
43+
float _Hotspots;
44+
float4 _Rect;
45+
46+
v2f vert (appdata v)
47+
{
48+
v2f o;
49+
o.vertex = UnityObjectToClipPos(v.vertex);
50+
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
51+
52+
return o;
53+
}
54+
55+
fixed4 frag (v2f i) : SV_Target
56+
{
57+
float width = _MainTex_TexelSize.z;
58+
float height = _MainTex_TexelSize.w;
59+
60+
float4 difference = _Rect;
61+
difference = difference + float4(-1, -1, 1, 1) * 2; // Margin
62+
63+
fixed4 col = tex2D(_MainTex, i.uv);
64+
if (i.uv.x < difference.x / width || i.uv.x > difference.z / width
65+
|| i.uv.y < difference.y / height || i.uv.y > difference.w / height) {
66+
col.xyz = col.xyz * 0.2;
67+
}
68+
if (_Hotspots > 0.01) {
69+
fixed3 neutral = tex2D(_NeutralTex, i.uv).xyz;
70+
fixed3 morphed = tex2D(_MainTex, i.uv).xyz;
71+
col = lerp(col, length(neutral - morphed) * float4(1, 0, 0, 1), _Hotspots);
72+
}
73+
return col;
74+
}
75+
ENDCG
76+
}
77+
}
78+
}

Assets/Hai/BlendshapeViewer/Shaders/HaiBlendshapeViewerRectOnly.shader.meta

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)