diff --git a/Runtime/SoftMask.cs b/Runtime/SoftMask.cs index a834c4c..6e1557b 100644 --- a/Runtime/SoftMask.cs +++ b/Runtime/SoftMask.cs @@ -77,17 +77,18 @@ [SerializeField] [Obsolete] private CommandBuffer _cb; private List _children = ListPool.Rent(); + private bool _hasResolutionChanged; private bool _hasSoftMaskBufferDrawn; private Mesh _mesh; private MaterialPropertyBlock _mpb; private Action _onBeforeCanvasRebuild; + private Action _onResolutionChanged; private SoftMask _parent; private Matrix4x4 _prevTransformMatrix; private Action _renderSoftMaskBuffer; private Canvas _rootCanvas; private Action _setDirtyAndNotify; - private Action _setSoftMaskDirty; - private UnityAction _setSoftMaskDirty2; + private UnityAction _setSoftMaskDirty; private MaskingShapeContainer _shapeContainer; internal RenderTexture _softMaskBuffer; private UnityAction _updateParentSoftMask; @@ -179,7 +180,11 @@ public bool partOfParent public float softness { get => m_Softness; - set => m_Softness = value; + set + { + softMaskingRange = new MinMax01(0, value); + m_Softness = value; + } } public bool hasSoftMaskBuffer => _softMaskBuffer; @@ -251,7 +256,7 @@ protected override void OnEnable() graphic.RegisterDirtyMaterialCallback( _updateParentSoftMask ?? (_updateParentSoftMask = UpdateParentSoftMask)); graphic.RegisterDirtyVerticesCallback( - _setSoftMaskDirty2 ?? (_setSoftMaskDirty2 = SetSoftMaskDirty)); + _setSoftMaskDirty ?? (_setSoftMaskDirty = SetSoftMaskDirty)); graphic.SetVerticesDirty(); } @@ -279,7 +284,7 @@ protected override void OnDisable() graphic.UnregisterDirtyMaterialCallback( _updateParentSoftMask ?? (_updateParentSoftMask = UpdateParentSoftMask)); graphic.UnregisterDirtyVerticesCallback( - _setSoftMaskDirty2 ?? (_setSoftMaskDirty2 = SetSoftMaskDirty)); + _setSoftMaskDirty ?? (_setSoftMaskDirty = SetSoftMaskDirty)); graphic.SetVerticesDirty(); } @@ -307,7 +312,7 @@ protected override void OnDestroy() _setDirtyAndNotify = null; _renderSoftMaskBuffer = null; _setSoftMaskDirty = null; - _setSoftMaskDirty2 = null; + _onResolutionChanged = null; _updateParentSoftMask = null; } @@ -424,7 +429,7 @@ private void OnBeforeCanvasRebuild() SetSoftMaskDirty(); } - if (!_viewChangeTrigger && _rootCanvas && _rootCanvas.renderMode == RenderMode.WorldSpace) + if (!_viewChangeTrigger && _rootCanvas) { UpdateCanvasViewChangeTrigger(CanvasViewChangeTrigger.Find(transform)); SetSoftMaskDirty(); @@ -451,13 +456,13 @@ private void UpdateCanvasViewChangeTrigger(CanvasViewChangeTrigger trigger) if (_viewChangeTrigger) { _viewChangeTrigger.onViewChange -= - _setSoftMaskDirty ?? (_setSoftMaskDirty = SetSoftMaskDirty); + _onResolutionChanged ?? (_onResolutionChanged = OnResolutionChanged); } if (trigger) { trigger.onViewChange += - _setSoftMaskDirty ?? (_setSoftMaskDirty = SetSoftMaskDirty); + _onResolutionChanged ?? (_onResolutionChanged = OnResolutionChanged); } } @@ -528,6 +533,12 @@ private void SetDirtyAndNotify() MaskUtilities.NotifyStencilStateChanged(this); } + private void OnResolutionChanged() + { + _hasResolutionChanged = true; + SetSoftMaskDirty(); + } + public void SetSoftMaskDirty() { if (isDirty) return; @@ -651,29 +662,26 @@ private void RenderSoftMaskBuffer() if (!IsInScreen()) { - if (_hasSoftMaskBufferDrawn) + if (_hasSoftMaskBufferDrawn || _hasResolutionChanged) { Profiler.BeginSample("(SM4UI)[SoftMask] RenderSoftMaskBuffer > Clear"); _cb.Clear(); _cb.SetRenderTarget(softMaskBuffer); - if (softMaskDepth == 0) - { - _cb.ClearRenderTarget(true, true, clearColor); - } - + _cb.ClearRenderTarget(true, true, clearColor); Graphics.ExecuteCommandBuffer(_cb); Profiler.EndSample(); } _hasSoftMaskBufferDrawn = false; + _hasResolutionChanged = false; return; } Profiler.BeginSample("(SM4UI)[SoftMask] RenderSoftMaskBuffer > Init command buffer"); _cb.Clear(); _cb.SetRenderTarget(softMaskBuffer); - if (softMaskDepth == 0) + if (softMaskDepth == 0 || _hasResolutionChanged) { _cb.ClearRenderTarget(true, true, clearColor); } @@ -683,13 +691,14 @@ private void RenderSoftMaskBuffer() var eyes = graphic.canvas.IsStereoCanvas() ? s_StereoEyes : s_MonoEyes; for (var i = 0; i < eyes.Length; i++) { - RenderSoftMaskBuffer(eyes[i]); + RenderSoftMaskBuffer(_cb, eyes[i]); } { Profiler.BeginSample("(SM4UI)[SoftMask] RenderSoftMaskBuffer > Execute command buffer"); Graphics.ExecuteCommandBuffer(_cb); _hasSoftMaskBufferDrawn = true; + _hasResolutionChanged = false; Logging.Log(this, $" >>>> SoftMaskBuffer '{softMaskBuffer.name}' will render."); Profiler.EndSample(); } @@ -704,12 +713,22 @@ private void RenderSoftMaskBuffer() onRenderSoftMaskBuffer?.Invoke(this); } - private void RenderSoftMaskBuffer(Camera.MonoOrStereoscopicEye eye) + private void RenderSoftMaskBuffer(CommandBuffer cb, Camera.MonoOrStereoscopicEye eye) { + if (_hasResolutionChanged) + { + var p = _parent; + while (p) + { + p.RenderSoftMaskBuffer(cb, eye); + p = p._parent; + } + } + { Profiler.BeginSample("(SM4UI)[SoftMask] RenderSoftMaskBuffer > SetVpMatricesCommandBuffer"); graphic.canvas.rootCanvas.GetViewProjectionMatrix(eye, out var viewMatrix, out var projectionMatrix); - _cb.SetViewProjectionMatrices(viewMatrix, projectionMatrix); + cb.SetViewProjectionMatrices(viewMatrix, projectionMatrix); Profiler.EndSample(); Profiler.BeginSample("(SM4UI)[SoftMask] RenderSoftMaskBuffer > ApplyMaterialPropertyBlock"); @@ -717,12 +736,12 @@ private void RenderSoftMaskBuffer(Camera.MonoOrStereoscopicEye eye) Profiler.EndSample(); } - if (eye != Camera.MonoOrStereoscopicEye.Right && _parent) + if (!_hasResolutionChanged && eye != Camera.MonoOrStereoscopicEye.Right && _parent) { Profiler.BeginSample("(SM4UI)[SoftMask] RenderSoftMaskBuffer > Copy texture from parent"); if (_parent.softMaskBuffer) { - _cb.CopyTexture(_parent.softMaskBuffer, softMaskBuffer); + _cb.Blit(_parent.softMaskBuffer, softMaskBuffer); } Profiler.EndSample(); @@ -733,7 +752,7 @@ private void RenderSoftMaskBuffer(Camera.MonoOrStereoscopicEye eye) Profiler.BeginSample("(SM4UI)[SoftMask] RenderSoftMaskBuffer > Set viewport"); var w = softMaskBuffer.width * 0.5f; var h = softMaskBuffer.height; - _cb.SetViewport(new Rect(w * (int)eye, 0f, w, h)); + cb.SetViewport(new Rect(w * (int)eye, 0f, w, h)); Profiler.EndSample(); } @@ -741,14 +760,14 @@ private void RenderSoftMaskBuffer(Camera.MonoOrStereoscopicEye eye) { Profiler.BeginSample("(SM4UI)[SoftMask] RenderSoftMaskBuffer > Draw mesh"); var softMaterial = SoftMaskUtils.GetSoftMaskingMaterial(MaskingShape.MaskingMethod.Additive); - _cb.DrawMesh(_mesh, transform.localToWorldMatrix, softMaterial, 0, 0, _mpb); + cb.DrawMesh(_mesh, transform.localToWorldMatrix, softMaterial, 0, 0, _mpb); Profiler.EndSample(); } if (_shapeContainer) { Profiler.BeginSample("(SM4UI)[SoftMask] RenderSoftMaskBuffer > Draw shapes"); - _shapeContainer.DrawSoftMaskBuffer(_cb, softMaskDepth); + _shapeContainer.DrawSoftMaskBuffer(cb, softMaskDepth); Profiler.EndSample(); } } diff --git a/Runtime/SoftMaskable.cs b/Runtime/SoftMaskable.cs index af44e40..01d9dc6 100755 --- a/Runtime/SoftMaskable.cs +++ b/Runtime/SoftMaskable.cs @@ -162,6 +162,7 @@ private static int GetStencilBitsAndSoftMask(Transform transform, out SoftMask n nearestMask = mask; if (FrameCache.TryGet(nearestMask, nameof(GetStencilBitsAndSoftMask), out stencilBits)) { + FrameCache.TryGet(nearestMask, nameof(GetStencilBitsAndSoftMask), out nearestSoftMask); Profiler.EndSample(); return stencilBits; } @@ -189,6 +190,7 @@ private static int GetStencilBitsAndSoftMask(Transform transform, out SoftMask n if (nearestMask) { FrameCache.Set(nearestMask, nameof(GetStencilBitsAndSoftMask), stencilBits); + FrameCache.Set(nearestMask, nameof(GetStencilBitsAndSoftMask), nearestSoftMask); } return stencilBits; diff --git a/Runtime/Utilities/CanvasViewChangeTrigger.cs b/Runtime/Utilities/CanvasViewChangeTrigger.cs index 6ad2fd6..079c2fb 100755 --- a/Runtime/Utilities/CanvasViewChangeTrigger.cs +++ b/Runtime/Utilities/CanvasViewChangeTrigger.cs @@ -15,6 +15,7 @@ public class CanvasViewChangeTrigger : MonoBehaviour private Canvas _canvas; private Action _checkViewProjectionMatrix; private int _lastCameraVpHash; + private int _lastResHash; /// /// Called when the component is enabled. @@ -53,15 +54,18 @@ private void OnDestroy() private void CheckViewProjectionMatrix() { - if (!_canvas || _canvas.renderMode != RenderMode.WorldSpace) return; + if (!_canvas) return; // Get the view and projection matrix of the Canvas. var prevHash = _lastCameraVpHash; _canvas.GetViewProjectionMatrix(out var vpMatrix); _lastCameraVpHash = vpMatrix.GetHashCode(); + var prevResHash = _lastResHash; + _lastResHash = Screen.currentResolution.GetHashCode(); + // The matrix has changed. - if (prevHash != _lastCameraVpHash) + if (prevHash != _lastCameraVpHash || prevResHash != _lastResHash) { Logging.Log(this, "ViewProjection changed."); onViewChange?.Invoke();