Skip to content

Commit

Permalink
fix: when changing resolution, display, or screen orientation, soft-m…
Browse files Browse the repository at this point in the history
…asking do not work properly
  • Loading branch information
mob-sakai committed Feb 11, 2024
1 parent ec60d90 commit dee7271
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 26 deletions.
67 changes: 43 additions & 24 deletions Runtime/SoftMask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,17 +77,18 @@ [SerializeField] [Obsolete]
private CommandBuffer _cb;

private List<SoftMask> _children = ListPool<SoftMask>.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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -251,7 +256,7 @@ protected override void OnEnable()
graphic.RegisterDirtyMaterialCallback(
_updateParentSoftMask ?? (_updateParentSoftMask = UpdateParentSoftMask));
graphic.RegisterDirtyVerticesCallback(
_setSoftMaskDirty2 ?? (_setSoftMaskDirty2 = SetSoftMaskDirty));
_setSoftMaskDirty ?? (_setSoftMaskDirty = SetSoftMaskDirty));
graphic.SetVerticesDirty();
}

Expand Down Expand Up @@ -279,7 +284,7 @@ protected override void OnDisable()
graphic.UnregisterDirtyMaterialCallback(
_updateParentSoftMask ?? (_updateParentSoftMask = UpdateParentSoftMask));
graphic.UnregisterDirtyVerticesCallback(
_setSoftMaskDirty2 ?? (_setSoftMaskDirty2 = SetSoftMaskDirty));
_setSoftMaskDirty ?? (_setSoftMaskDirty = SetSoftMaskDirty));
graphic.SetVerticesDirty();
}

Expand Down Expand Up @@ -307,7 +312,7 @@ protected override void OnDestroy()
_setDirtyAndNotify = null;
_renderSoftMaskBuffer = null;
_setSoftMaskDirty = null;
_setSoftMaskDirty2 = null;
_onResolutionChanged = null;
_updateParentSoftMask = null;
}

Expand Down Expand Up @@ -424,7 +429,7 @@ private void OnBeforeCanvasRebuild()
SetSoftMaskDirty();
}

if (!_viewChangeTrigger && _rootCanvas && _rootCanvas.renderMode == RenderMode.WorldSpace)
if (!_viewChangeTrigger && _rootCanvas)
{
UpdateCanvasViewChangeTrigger(CanvasViewChangeTrigger.Find(transform));
SetSoftMaskDirty();
Expand All @@ -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);
}
}

Expand Down Expand Up @@ -528,6 +533,12 @@ private void SetDirtyAndNotify()
MaskUtilities.NotifyStencilStateChanged(this);
}

private void OnResolutionChanged()
{
_hasResolutionChanged = true;
SetSoftMaskDirty();
}

public void SetSoftMaskDirty()
{
if (isDirty) return;
Expand Down Expand Up @@ -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);
}
Expand All @@ -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();
}
Expand All @@ -704,25 +713,35 @@ 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");
SoftMaskUtils.ApplyMaterialPropertyBlock(_mpb, softMaskDepth, graphic.mainTexture, softMaskingRange);
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();
Expand All @@ -733,22 +752,22 @@ 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();
}

if (_mesh)
{
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();
}
}
Expand Down
2 changes: 2 additions & 0 deletions Runtime/SoftMaskable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
Expand Down
8 changes: 6 additions & 2 deletions Runtime/Utilities/CanvasViewChangeTrigger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public class CanvasViewChangeTrigger : MonoBehaviour
private Canvas _canvas;
private Action _checkViewProjectionMatrix;
private int _lastCameraVpHash;
private int _lastResHash;

/// <summary>
/// Called when the component is enabled.
Expand Down Expand Up @@ -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();
Expand Down

0 comments on commit dee7271

Please sign in to comment.