feat: support graphic connector
The rendering material is automatically generated. You don't need to pre-generate the material. The generated materials are cached and properly batched. Close #75, close #76, close #80 BREAKING CHANGE: The name of the custom SoftMaskable shader must be changed. For more information, see the ‘Support soft masks with your custom shaders’ section of the README.vr
parent
0389363798
commit
34515216a3
|
@ -10,11 +10,14 @@ namespace Coffee.UIExtensions.Demos
|
||||||
[SerializeField] RawImage[] softMaskBufferViewer;
|
[SerializeField] RawImage[] softMaskBufferViewer;
|
||||||
[SerializeField] SoftMask[] softMask;
|
[SerializeField] SoftMask[] softMask;
|
||||||
[SerializeField] Text text;
|
[SerializeField] Text text;
|
||||||
|
[SerializeField] GameObject title;
|
||||||
|
|
||||||
|
|
||||||
// Use this for initialization
|
// Use this for initialization
|
||||||
void OnEnable()
|
void OnEnable()
|
||||||
{
|
{
|
||||||
|
title.SetActive(true);
|
||||||
|
|
||||||
text.text = string.Format("GPU: {0}\nDeviceType: {1}\nShaderLevel: {2}\nUVStartsAtTop: {3}",
|
text.text = string.Format("GPU: {0}\nDeviceType: {1}\nShaderLevel: {2}\nUVStartsAtTop: {3}",
|
||||||
SystemInfo.graphicsDeviceName,
|
SystemInfo.graphicsDeviceName,
|
||||||
SystemInfo.graphicsDeviceType,
|
SystemInfo.graphicsDeviceType,
|
||||||
|
@ -25,13 +28,6 @@ namespace Coffee.UIExtensions.Demos
|
||||||
{
|
{
|
||||||
softMaskBufferViewer[i].texture = softMask[i].softMaskBuffer;
|
softMaskBufferViewer[i].texture = softMask[i].softMaskBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update is called once per frame
|
|
||||||
void Update()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetWorldSpase(bool flag)
|
public void SetWorldSpase(bool flag)
|
||||||
|
@ -60,4 +56,4 @@ namespace Coffee.UIExtensions.Demos
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,106 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
|
||||||
|
namespace Coffee.UIExtensions
|
||||||
|
{
|
||||||
|
internal static class GraphicConnectorExtension
|
||||||
|
{
|
||||||
|
public static void SetVerticesDirtyEx(this Graphic graphic)
|
||||||
|
{
|
||||||
|
GraphicConnector.FindConnector(graphic).SetVerticesDirty(graphic);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SetMaterialDirtyEx(this Graphic graphic)
|
||||||
|
{
|
||||||
|
GraphicConnector.FindConnector(graphic).SetMaterialDirty(graphic);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Shader FindEffectShader(this Graphic graphic)
|
||||||
|
{
|
||||||
|
return GraphicConnector.FindConnector(graphic).FindEffectShader(graphic);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class GraphicConnector
|
||||||
|
{
|
||||||
|
|
||||||
|
private static readonly List<GraphicConnector> s_Connectors = new List<GraphicConnector>();
|
||||||
|
private static readonly Dictionary<Type, GraphicConnector> s_ConnectorMap = new Dictionary<Type, GraphicConnector>();
|
||||||
|
private static readonly GraphicConnector s_EmptyConnector = new GraphicConnector();
|
||||||
|
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
[UnityEditor.InitializeOnLoadMethod]
|
||||||
|
#endif
|
||||||
|
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
|
||||||
|
private static void Init()
|
||||||
|
{
|
||||||
|
AddConnector(new GraphicConnector());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static void AddConnector(GraphicConnector connector)
|
||||||
|
{
|
||||||
|
s_Connectors.Add(connector);
|
||||||
|
s_Connectors.Sort((x, y) => y.priority - x.priority);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GraphicConnector FindConnector(Graphic graphic)
|
||||||
|
{
|
||||||
|
if (!graphic) return s_EmptyConnector;
|
||||||
|
|
||||||
|
var type = graphic.GetType();
|
||||||
|
GraphicConnector connector = null;
|
||||||
|
if (s_ConnectorMap.TryGetValue(type, out connector)) return connector;
|
||||||
|
|
||||||
|
foreach (var c in s_Connectors)
|
||||||
|
{
|
||||||
|
if (!c.IsValid(graphic)) continue;
|
||||||
|
|
||||||
|
s_ConnectorMap.Add(type, c);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
return s_EmptyConnector;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Connector priority.
|
||||||
|
/// </summary>
|
||||||
|
protected virtual int priority
|
||||||
|
{
|
||||||
|
get { return -1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Find effect shader.
|
||||||
|
/// </summary>
|
||||||
|
public virtual Shader FindEffectShader(Graphic graphic)
|
||||||
|
{
|
||||||
|
return Shader.Find("Hidden/UI/SoftMaskable");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The connector is valid for the component.
|
||||||
|
/// </summary>
|
||||||
|
protected virtual bool IsValid(Graphic graphic)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void SetVerticesDirty(Graphic graphic)
|
||||||
|
{
|
||||||
|
if (graphic)
|
||||||
|
graphic.SetVerticesDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void SetMaterialDirty(Graphic graphic)
|
||||||
|
{
|
||||||
|
if (graphic)
|
||||||
|
graphic.SetMaterialDirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 0e702140c28f4425fac896f9394a31b1
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,80 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
|
||||||
|
namespace Coffee.UIExtensions
|
||||||
|
{
|
||||||
|
internal class MaterialCache
|
||||||
|
{
|
||||||
|
public delegate void ModifyAction(Material material, Graphic graphic);
|
||||||
|
|
||||||
|
static Dictionary<Hash128, MaterialEntry> materialMap = new Dictionary<Hash128, MaterialEntry>();
|
||||||
|
|
||||||
|
private class MaterialEntry
|
||||||
|
{
|
||||||
|
public Material material;
|
||||||
|
public int referenceCount;
|
||||||
|
|
||||||
|
public void Release()
|
||||||
|
{
|
||||||
|
if (material)
|
||||||
|
{
|
||||||
|
UnityEngine.Object.DestroyImmediate(material, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
material = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
[UnityEditor.InitializeOnLoadMethod]
|
||||||
|
private static void ClearCache()
|
||||||
|
{
|
||||||
|
foreach (var entry in materialMap.Values)
|
||||||
|
{
|
||||||
|
entry.Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
materialMap.Clear();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public static Material Register(Material material, Hash128 hash, Action<Material> onModify)
|
||||||
|
{
|
||||||
|
if (!hash.isValid) return null;
|
||||||
|
|
||||||
|
MaterialEntry entry;
|
||||||
|
if (!materialMap.TryGetValue(hash, out entry))
|
||||||
|
{
|
||||||
|
entry = new MaterialEntry()
|
||||||
|
{
|
||||||
|
material = new Material(material)
|
||||||
|
{
|
||||||
|
hideFlags = HideFlags.HideAndDontSave,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
onModify(entry.material);
|
||||||
|
materialMap.Add(hash, entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
entry.referenceCount++;
|
||||||
|
//Debug.LogFormat("Register: {0}, {1} (Total: {2})", hash, entry.referenceCount, materialMap.Count);
|
||||||
|
return entry.material;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Unregister(Hash128 hash)
|
||||||
|
{
|
||||||
|
MaterialEntry entry;
|
||||||
|
if (!hash.isValid || !materialMap.TryGetValue(hash, out entry)) return;
|
||||||
|
//Debug.LogFormat("Unregister: {0}, {1}", hash, entry.referenceCount -1);
|
||||||
|
|
||||||
|
if (--entry.referenceCount > 0) return;
|
||||||
|
|
||||||
|
entry.Release();
|
||||||
|
materialMap.Remove(hash);
|
||||||
|
//Debug.LogFormat("Unregister: Release Emtry: {0}, {1} (Total: {2})", hash, entry.referenceCount, materialMap.Count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: be6c8de8d4ec241fdbfad99aca2497d8
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -1,7 +1,4 @@
|
||||||
using System.Collections;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Text;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.Rendering;
|
using UnityEngine.Rendering;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
using System.Collections;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Generic;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.Rendering;
|
using UnityEngine.Rendering;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using MaskIntr = UnityEngine.SpriteMaskInteraction;
|
using MaskIntr = UnityEngine.SpriteMaskInteraction;
|
||||||
using UnityEngine.Serialization;
|
|
||||||
|
|
||||||
namespace Coffee.UIExtensions
|
namespace Coffee.UIExtensions
|
||||||
{
|
{
|
||||||
|
@ -17,18 +15,15 @@ namespace Coffee.UIExtensions
|
||||||
#else
|
#else
|
||||||
[ExecuteInEditMode]
|
[ExecuteInEditMode]
|
||||||
# endif
|
# endif
|
||||||
public class SoftMaskable : MonoBehaviour, IMaterialModifier, ICanvasRaycastFilter, ISerializationCallbackReceiver
|
public class SoftMaskable : MonoBehaviour, IMaterialModifier, ICanvasRaycastFilter
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
, ISerializationCallbackReceiver
|
||||||
|
# endif
|
||||||
{
|
{
|
||||||
//################################
|
|
||||||
// Constant or Static Members.
|
|
||||||
//################################
|
|
||||||
const int kVisibleInside = (1 << 0) + (1 << 2) + (1 << 4) + (1 << 6);
|
const int kVisibleInside = (1 << 0) + (1 << 2) + (1 << 4) + (1 << 6);
|
||||||
const int kVisibleOutside = (2 << 0) + (2 << 2) + (2 << 4) + (2 << 6);
|
const int kVisibleOutside = (2 << 0) + (2 << 2) + (2 << 4) + (2 << 6);
|
||||||
|
static readonly Hash128 k_InvalidHash = new Hash128();
|
||||||
|
|
||||||
|
|
||||||
//################################
|
|
||||||
// Serialize Members.
|
|
||||||
//################################
|
|
||||||
[Tooltip("The graphic will be visible only in areas where no mask is present.")]
|
[Tooltip("The graphic will be visible only in areas where no mask is present.")]
|
||||||
[System.Obsolete]
|
[System.Obsolete]
|
||||||
[HideInInspector]
|
[HideInInspector]
|
||||||
|
@ -41,10 +36,16 @@ namespace Coffee.UIExtensions
|
||||||
[Tooltip("Use soft-masked raycast target.\n\nNote: This option is expensive.")]
|
[Tooltip("Use soft-masked raycast target.\n\nNote: This option is expensive.")]
|
||||||
[SerializeField] bool m_RaycastFilter = false;
|
[SerializeField] bool m_RaycastFilter = false;
|
||||||
|
|
||||||
|
Graphic _graphic = null;
|
||||||
|
SoftMask _softMask = null;
|
||||||
|
Material _maskMaterial = null;
|
||||||
|
static int s_SoftMaskTexId;
|
||||||
|
static int s_StencilCompId;
|
||||||
|
static int s_MaskInteractionId;
|
||||||
|
static List<SoftMaskable> s_ActiveSoftMaskables;
|
||||||
|
static int[] s_Interactions = new int[4];
|
||||||
|
Hash128 _effectMaterialHash;
|
||||||
|
|
||||||
//################################
|
|
||||||
// Public Members.
|
|
||||||
//################################
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Perform material modification in this function.
|
/// Perform material modification in this function.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -71,34 +72,46 @@ namespace Coffee.UIExtensions
|
||||||
parentTransform = parentTransform.parent;
|
parentTransform = parentTransform.parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
Material result = baseMaterial;
|
var oldHash = _effectMaterialHash;
|
||||||
|
var modifiedMaterial = baseMaterial;
|
||||||
if (_softMask)
|
if (_softMask)
|
||||||
{
|
{
|
||||||
result = new Material(baseMaterial);
|
_effectMaterialHash = GetMaterialHash(baseMaterial);
|
||||||
result.hideFlags = HideFlags.HideAndDontSave;
|
modifiedMaterial = MaterialCache.Register(baseMaterial, _effectMaterialHash, mat =>
|
||||||
result.SetTexture(s_SoftMaskTexId, _softMask.softMaskBuffer);
|
{
|
||||||
result.SetInt(s_StencilCompId, m_UseStencil ? (int)CompareFunction.Equal : (int)CompareFunction.Always);
|
Debug.Log(mat.shader.name);
|
||||||
result.SetVector(s_MaskInteractionId, new Vector4(
|
mat.shader = Shader.Find(string.Format("Hidden/{0} (SoftMaskable)", mat.shader.name));
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
mat.EnableKeyword("SOFTMASK_EDITOR");
|
||||||
|
#endif
|
||||||
|
mat.SetTexture(s_SoftMaskTexId, _softMask.softMaskBuffer);
|
||||||
|
mat.SetInt(s_StencilCompId, m_UseStencil ? (int)CompareFunction.Equal : (int)CompareFunction.Always);
|
||||||
|
mat.SetVector(s_MaskInteractionId, new Vector4(
|
||||||
(m_MaskInteraction & 0x3),
|
(m_MaskInteraction & 0x3),
|
||||||
((m_MaskInteraction >> 2) & 0x3),
|
((m_MaskInteraction >> 2) & 0x3),
|
||||||
((m_MaskInteraction >> 4) & 0x3),
|
((m_MaskInteraction >> 4) & 0x3),
|
||||||
((m_MaskInteraction >> 6) & 0x3)
|
((m_MaskInteraction >> 6) & 0x3)
|
||||||
));
|
));
|
||||||
|
});
|
||||||
StencilMaterial.Remove(baseMaterial);
|
|
||||||
ReleaseMaterial(ref _maskMaterial);
|
ReleaseMaterial(ref _maskMaterial);
|
||||||
_maskMaterial = result;
|
_maskMaterial = modifiedMaterial;
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
|
||||||
result.EnableKeyword("SOFTMASK_EDITOR");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
baseMaterial.SetTexture(s_SoftMaskTexId, Texture2D.whiteTexture);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
MaterialCache.Unregister(oldHash);
|
||||||
|
return modifiedMaterial;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Hash128 GetMaterialHash(Material material)
|
||||||
|
{
|
||||||
|
if (!isActiveAndEnabled || !material || !material.shader)
|
||||||
|
return k_InvalidHash;
|
||||||
|
|
||||||
|
return new Hash128(
|
||||||
|
(uint) material.GetInstanceID(),
|
||||||
|
(uint) m_MaskInteraction,
|
||||||
|
(uint) (m_UseStencil ? 1 : 0),
|
||||||
|
0
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -111,15 +124,10 @@ namespace Coffee.UIExtensions
|
||||||
{
|
{
|
||||||
if (!isActiveAndEnabled || !_softMask)
|
if (!isActiveAndEnabled || !_softMask)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (!RectTransformUtility.RectangleContainsScreenPoint(transform as RectTransform, sp, eventCamera))
|
if (!RectTransformUtility.RectangleContainsScreenPoint(transform as RectTransform, sp, eventCamera))
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
if (!m_RaycastFilter)
|
||||||
else if (!m_RaycastFilter)
|
|
||||||
{
|
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
var sm = _softMask;
|
var sm = _softMask;
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
|
@ -144,7 +152,7 @@ namespace Coffee.UIExtensions
|
||||||
if (m_MaskInteraction != intValue)
|
if (m_MaskInteraction != intValue)
|
||||||
{
|
{
|
||||||
m_MaskInteraction = intValue;
|
m_MaskInteraction = intValue;
|
||||||
graphic.SetMaterialDirty();
|
graphic.SetMaterialDirtyEx();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -177,37 +185,9 @@ namespace Coffee.UIExtensions
|
||||||
public void SetMaskInteraction(SpriteMaskInteraction layer0, SpriteMaskInteraction layer1, SpriteMaskInteraction layer2, SpriteMaskInteraction layer3)
|
public void SetMaskInteraction(SpriteMaskInteraction layer0, SpriteMaskInteraction layer1, SpriteMaskInteraction layer2, SpriteMaskInteraction layer3)
|
||||||
{
|
{
|
||||||
m_MaskInteraction = (int)layer0 + ((int)layer1 << 2) + ((int)layer2 << 4) + ((int)layer3 << 6);
|
m_MaskInteraction = (int)layer0 + ((int)layer1 << 2) + ((int)layer2 << 4) + ((int)layer3 << 6);
|
||||||
if (graphic)
|
graphic.SetMaterialDirtyEx();
|
||||||
{
|
|
||||||
graphic.SetMaterialDirty();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//################################
|
|
||||||
// Private Members.
|
|
||||||
//################################
|
|
||||||
Graphic _graphic = null;
|
|
||||||
SoftMask _softMask = null;
|
|
||||||
Material _maskMaterial = null;
|
|
||||||
static int s_SoftMaskTexId;
|
|
||||||
static int s_StencilCompId;
|
|
||||||
static int s_MaskInteractionId;
|
|
||||||
static List<SoftMaskable> s_ActiveSoftMaskables;
|
|
||||||
static int[] s_Interactions = new int[4];
|
|
||||||
static Material s_DefaultMaterial;
|
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
|
||||||
/// <summary>
|
|
||||||
/// This function is called when the script is loaded or a value is changed in the inspector (Called in the editor only).
|
|
||||||
/// </summary>
|
|
||||||
void OnValidate()
|
|
||||||
{
|
|
||||||
if (graphic)
|
|
||||||
{
|
|
||||||
graphic.SetMaterialDirty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This function is called when the object becomes enabled and active.
|
/// This function is called when the object becomes enabled and active.
|
||||||
|
@ -229,10 +209,6 @@ namespace Coffee.UIExtensions
|
||||||
var g = graphic;
|
var g = graphic;
|
||||||
if (g)
|
if (g)
|
||||||
{
|
{
|
||||||
if (!g.material || g.material == Graphic.defaultGraphicMaterial)
|
|
||||||
{
|
|
||||||
g.material = s_DefaultMaterial ?? (s_DefaultMaterial = new Material(Resources.Load<Shader>("UI-Default-SoftMask")) { hideFlags = HideFlags.HideAndDontSave, });
|
|
||||||
}
|
|
||||||
g.SetMaterialDirty();
|
g.SetMaterialDirty();
|
||||||
}
|
}
|
||||||
_softMask = null;
|
_softMask = null;
|
||||||
|
@ -248,15 +224,14 @@ namespace Coffee.UIExtensions
|
||||||
var g = graphic;
|
var g = graphic;
|
||||||
if (g)
|
if (g)
|
||||||
{
|
{
|
||||||
if (g.material == s_DefaultMaterial)
|
|
||||||
{
|
|
||||||
g.material = null;
|
|
||||||
}
|
|
||||||
g.SetMaterialDirty();
|
g.SetMaterialDirty();
|
||||||
}
|
}
|
||||||
ReleaseMaterial(ref _maskMaterial);
|
ReleaseMaterial(ref _maskMaterial);
|
||||||
|
|
||||||
_softMask = null;
|
_softMask = null;
|
||||||
|
|
||||||
|
MaterialCache.Unregister(_effectMaterialHash);
|
||||||
|
_effectMaterialHash = k_InvalidHash;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -266,8 +241,6 @@ namespace Coffee.UIExtensions
|
||||||
{
|
{
|
||||||
if (mat)
|
if (mat)
|
||||||
{
|
{
|
||||||
StencilMaterial.Remove(mat);
|
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
if (!Application.isPlaying)
|
if (!Application.isPlaying)
|
||||||
{
|
{
|
||||||
|
@ -283,6 +256,15 @@ namespace Coffee.UIExtensions
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
/// <summary>
|
||||||
|
/// This function is called when the script is loaded or a value is changed in the inspector (Called in the editor only).
|
||||||
|
/// </summary>
|
||||||
|
private void OnValidate()
|
||||||
|
{
|
||||||
|
graphic.SetMaterialDirtyEx();
|
||||||
|
}
|
||||||
|
|
||||||
void ISerializationCallbackReceiver.OnBeforeSerialize()
|
void ISerializationCallbackReceiver.OnBeforeSerialize()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -296,6 +278,18 @@ namespace Coffee.UIExtensions
|
||||||
m_MaskInteraction = (2 << 0) + (2 << 2) + (2 << 4) + (2 << 6);
|
m_MaskInteraction = (2 << 0) + (2 << 2) + (2 << 4) + (2 << 6);
|
||||||
}
|
}
|
||||||
#pragma warning restore 0612
|
#pragma warning restore 0612
|
||||||
|
|
||||||
|
var current = this;
|
||||||
|
UnityEditor.EditorApplication.delayCall += () =>
|
||||||
|
{
|
||||||
|
if (current && graphic && graphic.material && graphic.material.shader && graphic.material.shader.name == "Hidden/UI/Default (SoftMaskable)")
|
||||||
|
{
|
||||||
|
Debug.LogFormat("OnAfterDeserialize: reset material {0}",current);
|
||||||
|
graphic.material = null;
|
||||||
|
graphic.SetMaterialDirtyEx();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
Shader "UI/Default-SoftMask"
|
Shader "Hidden/UI/Default (SoftMaskable)"
|
||||||
{
|
{
|
||||||
Properties
|
Properties
|
||||||
{
|
{
|
||||||
|
@ -52,7 +52,7 @@ Shader "UI/Default-SoftMask"
|
||||||
|
|
||||||
#include "UnityCG.cginc"
|
#include "UnityCG.cginc"
|
||||||
#include "UnityUI.cginc"
|
#include "UnityUI.cginc"
|
||||||
|
|
||||||
#pragma multi_compile __ UNITY_UI_CLIP_RECT
|
#pragma multi_compile __ UNITY_UI_CLIP_RECT
|
||||||
#pragma multi_compile __ UNITY_UI_ALPHACLIP
|
#pragma multi_compile __ UNITY_UI_ALPHACLIP
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
Shader "TextMeshPro/Distance Field (SoftMaskable)" {
|
Shader "Hidden/TextMeshPro/Distance Field (SoftMaskable)" {
|
||||||
|
|
||||||
Properties {
|
Properties {
|
||||||
_FaceTex ("Face Texture", 2D) = "white" {}
|
_FaceTex ("Face Texture", 2D) = "white" {}
|
||||||
|
@ -35,7 +35,7 @@ Properties {
|
||||||
_ReflectOutlineColor("Reflection Color", Color) = (0,0,0,1)
|
_ReflectOutlineColor("Reflection Color", Color) = (0,0,0,1)
|
||||||
_Cube ("Reflection Cubemap", Cube) = "black" { /* TexGen CubeReflect */ }
|
_Cube ("Reflection Cubemap", Cube) = "black" { /* TexGen CubeReflect */ }
|
||||||
_EnvMatrixRotation ("Texture Rotation", vector) = (0, 0, 0, 0)
|
_EnvMatrixRotation ("Texture Rotation", vector) = (0, 0, 0, 0)
|
||||||
|
|
||||||
|
|
||||||
_UnderlayColor ("Border Color", Color) = (0,0,0, 0.5)
|
_UnderlayColor ("Border Color", Color) = (0,0,0, 0.5)
|
||||||
_UnderlayOffsetX ("Border OffsetX", Range(-1,1)) = 0
|
_UnderlayOffsetX ("Border OffsetX", Range(-1,1)) = 0
|
||||||
|
@ -67,7 +67,7 @@ Properties {
|
||||||
|
|
||||||
_VertexOffsetX ("Vertex OffsetX", float) = 0
|
_VertexOffsetX ("Vertex OffsetX", float) = 0
|
||||||
_VertexOffsetY ("Vertex OffsetY", float) = 0
|
_VertexOffsetY ("Vertex OffsetY", float) = 0
|
||||||
|
|
||||||
_MaskCoord ("Mask Coordinates", vector) = (0, 0, 32767, 32767)
|
_MaskCoord ("Mask Coordinates", vector) = (0, 0, 32767, 32767)
|
||||||
_ClipRect ("Clip Rect", vector) = (-32767, -32767, 32767, 32767)
|
_ClipRect ("Clip Rect", vector) = (-32767, -32767, 32767, 32767)
|
||||||
_MaskSoftnessX ("Mask SoftnessX", float) = 0
|
_MaskSoftnessX ("Mask SoftnessX", float) = 0
|
||||||
|
@ -95,7 +95,7 @@ SubShader {
|
||||||
{
|
{
|
||||||
Ref [_Stencil]
|
Ref [_Stencil]
|
||||||
Comp [_StencilComp]
|
Comp [_StencilComp]
|
||||||
Pass [_StencilOp]
|
Pass [_StencilOp]
|
||||||
ReadMask [_StencilReadMask]
|
ReadMask [_StencilReadMask]
|
||||||
WriteMask [_StencilWriteMask]
|
WriteMask [_StencilWriteMask]
|
||||||
}
|
}
|
||||||
|
@ -126,7 +126,7 @@ SubShader {
|
||||||
#include "UnityUI.cginc"
|
#include "UnityUI.cginc"
|
||||||
#include "Assets/TextMesh Pro/Resources/Shaders/TMPro_Properties.cginc"
|
#include "Assets/TextMesh Pro/Resources/Shaders/TMPro_Properties.cginc"
|
||||||
#include "Assets/TextMesh Pro/Resources/Shaders/TMPro.cginc"
|
#include "Assets/TextMesh Pro/Resources/Shaders/TMPro.cginc"
|
||||||
|
|
||||||
#include "Packages/com.coffee.softmask-for-ugui/Shaders/SoftMask.cginc"
|
#include "Packages/com.coffee.softmask-for-ugui/Shaders/SoftMask.cginc"
|
||||||
#pragma shader_feature __ SOFTMASK_EDITOR
|
#pragma shader_feature __ SOFTMASK_EDITOR
|
||||||
|
|
||||||
|
@ -146,7 +146,7 @@ SubShader {
|
||||||
float4 param : TEXCOORD1; // alphaClip, scale, bias, weight
|
float4 param : TEXCOORD1; // alphaClip, scale, bias, weight
|
||||||
float4 mask : TEXCOORD2; // Position in object space(xy), pixel Size(zw)
|
float4 mask : TEXCOORD2; // Position in object space(xy), pixel Size(zw)
|
||||||
float3 viewDir : TEXCOORD3;
|
float3 viewDir : TEXCOORD3;
|
||||||
|
|
||||||
#if (UNDERLAY_ON || UNDERLAY_INNER)
|
#if (UNDERLAY_ON || UNDERLAY_INNER)
|
||||||
float4 texcoord2 : TEXCOORD4; // u,v, scale, bias
|
float4 texcoord2 : TEXCOORD4; // u,v, scale, bias
|
||||||
fixed4 underlayColor : COLOR1;
|
fixed4 underlayColor : COLOR1;
|
||||||
|
@ -181,7 +181,7 @@ SubShader {
|
||||||
float bias =(.5 - weight) + (.5 / scale);
|
float bias =(.5 - weight) + (.5 / scale);
|
||||||
|
|
||||||
float alphaClip = (1.0 - _OutlineWidth*_ScaleRatioA - _OutlineSoftness*_ScaleRatioA);
|
float alphaClip = (1.0 - _OutlineWidth*_ScaleRatioA - _OutlineSoftness*_ScaleRatioA);
|
||||||
|
|
||||||
#if GLOW_ON
|
#if GLOW_ON
|
||||||
alphaClip = min(alphaClip, 1.0 - _GlowOffset * _ScaleRatioB - _GlowOuter * _ScaleRatioB);
|
alphaClip = min(alphaClip, 1.0 - _GlowOffset * _ScaleRatioB - _GlowOuter * _ScaleRatioB);
|
||||||
#endif
|
#endif
|
||||||
|
@ -232,7 +232,7 @@ SubShader {
|
||||||
fixed4 PixShader(pixel_t input) : SV_Target
|
fixed4 PixShader(pixel_t input) : SV_Target
|
||||||
{
|
{
|
||||||
float c = tex2D(_MainTex, input.atlas).a;
|
float c = tex2D(_MainTex, input.atlas).a;
|
||||||
|
|
||||||
#ifndef UNDERLAY_ON
|
#ifndef UNDERLAY_ON
|
||||||
clip(c - input.param.x);
|
clip(c - input.param.x);
|
||||||
#endif
|
#endif
|
||||||
|
@ -249,7 +249,7 @@ SubShader {
|
||||||
half4 outlineColor = _OutlineColor;
|
half4 outlineColor = _OutlineColor;
|
||||||
|
|
||||||
faceColor.rgb *= input.color.rgb;
|
faceColor.rgb *= input.color.rgb;
|
||||||
|
|
||||||
faceColor *= tex2D(_FaceTex, input.textures.xy + float2(_FaceUVSpeedX, _FaceUVSpeedY) * _Time.y);
|
faceColor *= tex2D(_FaceTex, input.textures.xy + float2(_FaceUVSpeedX, _FaceUVSpeedY) * _Time.y);
|
||||||
outlineColor *= tex2D(_OutlineTex, input.textures.zw + float2(_OutlineUVSpeedX, _OutlineUVSpeedY) * _Time.y);
|
outlineColor *= tex2D(_OutlineTex, input.textures.zw + float2(_OutlineUVSpeedX, _OutlineUVSpeedY) * _Time.y);
|
||||||
|
|
||||||
|
@ -294,9 +294,9 @@ SubShader {
|
||||||
half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(input.mask.xy)) * input.mask.zw);
|
half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(input.mask.xy)) * input.mask.zw);
|
||||||
faceColor *= m.x * m.y;
|
faceColor *= m.x * m.y;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
faceColor *= SoftMask(input.position, input.worldPosition);
|
faceColor *= SoftMask(input.position, input.worldPosition);
|
||||||
|
|
||||||
#if UNITY_UI_ALPHACLIP
|
#if UNITY_UI_ALPHACLIP
|
||||||
clip(faceColor.a - 0.001);
|
clip(faceColor.a - 0.001);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
// - No Glow Option
|
// - No Glow Option
|
||||||
// - Softness is applied on both side of the outline
|
// - Softness is applied on both side of the outline
|
||||||
|
|
||||||
Shader "TextMeshPro/Mobile/Distance Field (SoftMaskable)" {
|
Shader "Hidden/TextMeshPro/Mobile/Distance Field (SoftMaskable)" {
|
||||||
|
|
||||||
Properties {
|
Properties {
|
||||||
_FaceColor ("Face Color", Color) = (1,1,1,1)
|
_FaceColor ("Face Color", Color) = (1,1,1,1)
|
||||||
|
@ -41,18 +41,18 @@ Properties {
|
||||||
_ClipRect ("Clip Rect", vector) = (-32767, -32767, 32767, 32767)
|
_ClipRect ("Clip Rect", vector) = (-32767, -32767, 32767, 32767)
|
||||||
_MaskSoftnessX ("Mask SoftnessX", float) = 0
|
_MaskSoftnessX ("Mask SoftnessX", float) = 0
|
||||||
_MaskSoftnessY ("Mask SoftnessY", float) = 0
|
_MaskSoftnessY ("Mask SoftnessY", float) = 0
|
||||||
|
|
||||||
_StencilComp ("Stencil Comparison", Float) = 8
|
_StencilComp ("Stencil Comparison", Float) = 8
|
||||||
_Stencil ("Stencil ID", Float) = 0
|
_Stencil ("Stencil ID", Float) = 0
|
||||||
_StencilOp ("Stencil Operation", Float) = 0
|
_StencilOp ("Stencil Operation", Float) = 0
|
||||||
_StencilWriteMask ("Stencil Write Mask", Float) = 255
|
_StencilWriteMask ("Stencil Write Mask", Float) = 255
|
||||||
_StencilReadMask ("Stencil Read Mask", Float) = 255
|
_StencilReadMask ("Stencil Read Mask", Float) = 255
|
||||||
|
|
||||||
_ColorMask ("Color Mask", Float) = 15
|
_ColorMask ("Color Mask", Float) = 15
|
||||||
}
|
}
|
||||||
|
|
||||||
SubShader {
|
SubShader {
|
||||||
Tags
|
Tags
|
||||||
{
|
{
|
||||||
"Queue"="Transparent"
|
"Queue"="Transparent"
|
||||||
"IgnoreProjector"="True"
|
"IgnoreProjector"="True"
|
||||||
|
@ -64,7 +64,7 @@ SubShader {
|
||||||
{
|
{
|
||||||
Ref [_Stencil]
|
Ref [_Stencil]
|
||||||
Comp [_StencilComp]
|
Comp [_StencilComp]
|
||||||
Pass [_StencilOp]
|
Pass [_StencilOp]
|
||||||
ReadMask [_StencilReadMask]
|
ReadMask [_StencilReadMask]
|
||||||
WriteMask [_StencilWriteMask]
|
WriteMask [_StencilWriteMask]
|
||||||
}
|
}
|
||||||
|
@ -94,7 +94,7 @@ SubShader {
|
||||||
#include "UnityCG.cginc"
|
#include "UnityCG.cginc"
|
||||||
#include "UnityUI.cginc"
|
#include "UnityUI.cginc"
|
||||||
#include "Assets/TextMesh Pro/Resources/Shaders/TMPro_Properties.cginc"
|
#include "Assets/TextMesh Pro/Resources/Shaders/TMPro_Properties.cginc"
|
||||||
|
|
||||||
#include "Packages/com.coffee.softmask-for-ugui/Shaders/SoftMask.cginc"
|
#include "Packages/com.coffee.softmask-for-ugui/Shaders/SoftMask.cginc"
|
||||||
#pragma shader_feature __ SOFTMASK_EDITOR
|
#pragma shader_feature __ SOFTMASK_EDITOR
|
||||||
|
|
||||||
|
@ -132,7 +132,7 @@ SubShader {
|
||||||
|
|
||||||
float2 pixelSize = vPosition.w;
|
float2 pixelSize = vPosition.w;
|
||||||
pixelSize /= float2(_ScaleX, _ScaleY) * abs(mul((float2x2)UNITY_MATRIX_P, _ScreenParams.xy));
|
pixelSize /= float2(_ScaleX, _ScaleY) * abs(mul((float2x2)UNITY_MATRIX_P, _ScreenParams.xy));
|
||||||
|
|
||||||
float scale = rsqrt(dot(pixelSize, pixelSize));
|
float scale = rsqrt(dot(pixelSize, pixelSize));
|
||||||
scale *= abs(input.texcoord1.y) * _GradientScale * 1.5;
|
scale *= abs(input.texcoord1.y) * _GradientScale * 1.5;
|
||||||
if(UNITY_MATRIX_P[3][3] == 0) scale = lerp(abs(scale) * (1 - _PerspectiveFilter), scale, abs(dot(UnityObjectToWorldNormal(input.normal.xyz), normalize(WorldSpaceViewDir(vert)))));
|
if(UNITY_MATRIX_P[3][3] == 0) scale = lerp(abs(scale) * (1 - _PerspectiveFilter), scale, abs(dot(UnityObjectToWorldNormal(input.normal.xyz), normalize(WorldSpaceViewDir(vert)))));
|
||||||
|
@ -223,9 +223,9 @@ SubShader {
|
||||||
#if (UNDERLAY_ON | UNDERLAY_INNER)
|
#if (UNDERLAY_ON | UNDERLAY_INNER)
|
||||||
c *= input.texcoord1.z;
|
c *= input.texcoord1.z;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
c *= SoftMask(input.vertex, input.worldPosition);
|
c *= SoftMask(input.vertex, input.worldPosition);
|
||||||
|
|
||||||
#if UNITY_UI_ALPHACLIP
|
#if UNITY_UI_ALPHACLIP
|
||||||
clip(c.a - 0.001);
|
clip(c.a - 0.001);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
Shader "TextMeshPro/Sprite (SoftMaskable)"
|
Shader "Hidden/TextMeshPro/Sprite (SoftMaskable)"
|
||||||
{
|
{
|
||||||
Properties
|
Properties
|
||||||
{
|
{
|
||||||
_MainTex ("Sprite Texture", 2D) = "white" {}
|
_MainTex ("Sprite Texture", 2D) = "white" {}
|
||||||
_Color ("Tint", Color) = (1,1,1,1)
|
_Color ("Tint", Color) = (1,1,1,1)
|
||||||
|
|
||||||
_StencilComp ("Stencil Comparison", Float) = 8
|
_StencilComp ("Stencil Comparison", Float) = 8
|
||||||
_Stencil ("Stencil ID", Float) = 0
|
_Stencil ("Stencil ID", Float) = 0
|
||||||
_StencilOp ("Stencil Operation", Float) = 0
|
_StencilOp ("Stencil Operation", Float) = 0
|
||||||
|
@ -20,19 +20,19 @@ Shader "TextMeshPro/Sprite (SoftMaskable)"
|
||||||
SubShader
|
SubShader
|
||||||
{
|
{
|
||||||
Tags
|
Tags
|
||||||
{
|
{
|
||||||
"Queue"="Transparent"
|
"Queue"="Transparent"
|
||||||
"IgnoreProjector"="True"
|
"IgnoreProjector"="True"
|
||||||
"RenderType"="Transparent"
|
"RenderType"="Transparent"
|
||||||
"PreviewType"="Plane"
|
"PreviewType"="Plane"
|
||||||
"CanUseSpriteAtlas"="True"
|
"CanUseSpriteAtlas"="True"
|
||||||
}
|
}
|
||||||
|
|
||||||
Stencil
|
Stencil
|
||||||
{
|
{
|
||||||
Ref [_Stencil]
|
Ref [_Stencil]
|
||||||
Comp [_StencilComp]
|
Comp [_StencilComp]
|
||||||
Pass [_StencilOp]
|
Pass [_StencilOp]
|
||||||
ReadMask [_StencilReadMask]
|
ReadMask [_StencilReadMask]
|
||||||
WriteMask [_StencilWriteMask]
|
WriteMask [_StencilWriteMask]
|
||||||
}
|
}
|
||||||
|
@ -55,10 +55,10 @@ Shader "TextMeshPro/Sprite (SoftMaskable)"
|
||||||
|
|
||||||
#pragma multi_compile __ UNITY_UI_CLIP_RECT
|
#pragma multi_compile __ UNITY_UI_CLIP_RECT
|
||||||
#pragma multi_compile __ UNITY_UI_ALPHACLIP
|
#pragma multi_compile __ UNITY_UI_ALPHACLIP
|
||||||
|
|
||||||
#include "Packages/com.coffee.softmask-for-ugui/Shaders/SoftMask.cginc"
|
#include "Packages/com.coffee.softmask-for-ugui/Shaders/SoftMask.cginc"
|
||||||
#pragma shader_feature __ SOFTMASK_EDITOR
|
#pragma shader_feature __ SOFTMASK_EDITOR
|
||||||
|
|
||||||
struct appdata_t
|
struct appdata_t
|
||||||
{
|
{
|
||||||
float4 vertex : POSITION;
|
float4 vertex : POSITION;
|
||||||
|
@ -73,7 +73,7 @@ Shader "TextMeshPro/Sprite (SoftMaskable)"
|
||||||
half2 texcoord : TEXCOORD0;
|
half2 texcoord : TEXCOORD0;
|
||||||
float4 worldPosition : TEXCOORD1;
|
float4 worldPosition : TEXCOORD1;
|
||||||
};
|
};
|
||||||
|
|
||||||
fixed4 _Color;
|
fixed4 _Color;
|
||||||
fixed4 _TextureSampleAdd;
|
fixed4 _TextureSampleAdd;
|
||||||
float4 _ClipRect;
|
float4 _ClipRect;
|
||||||
|
@ -85,11 +85,11 @@ Shader "TextMeshPro/Sprite (SoftMaskable)"
|
||||||
OUT.vertex = UnityObjectToClipPos(OUT.worldPosition);
|
OUT.vertex = UnityObjectToClipPos(OUT.worldPosition);
|
||||||
|
|
||||||
OUT.texcoord = IN.texcoord;
|
OUT.texcoord = IN.texcoord;
|
||||||
|
|
||||||
#ifdef UNITY_HALF_TEXEL_OFFSET
|
#ifdef UNITY_HALF_TEXEL_OFFSET
|
||||||
OUT.vertex.xy += (_ScreenParams.zw-1.0)*float2(-1,1);
|
OUT.vertex.xy += (_ScreenParams.zw-1.0)*float2(-1,1);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
OUT.color = IN.color * _Color;
|
OUT.color = IN.color * _Color;
|
||||||
return OUT;
|
return OUT;
|
||||||
}
|
}
|
||||||
|
@ -99,13 +99,13 @@ Shader "TextMeshPro/Sprite (SoftMaskable)"
|
||||||
fixed4 frag(v2f IN) : SV_Target
|
fixed4 frag(v2f IN) : SV_Target
|
||||||
{
|
{
|
||||||
half4 color = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd) * IN.color;
|
half4 color = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd) * IN.color;
|
||||||
|
|
||||||
#if UNITY_UI_CLIP_RECT
|
#if UNITY_UI_CLIP_RECT
|
||||||
color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect);
|
color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
color.a *= SoftMask(IN.vertex, IN.worldPosition);
|
color.a *= SoftMask(IN.vertex, IN.worldPosition);
|
||||||
|
|
||||||
#ifdef UNITY_UI_ALPHACLIP
|
#ifdef UNITY_UI_ALPHACLIP
|
||||||
clip (color.a - 0.001);
|
clip (color.a - 0.001);
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue