|
|
- using System.Collections.Generic;
- using UnityEngine;
- using UnityEngine.Rendering;
- using UnityEngine.UI;
-
- namespace LeTai.TrueShadow
- {
- public partial class ShadowRenderer
- {
- // TODO: cleanup unused mask materials
- static readonly Dictionary<(bool, Material), Material> MASK_MATERIALS_CACHE =
- new Dictionary<(bool, Material), Material>();
-
- internal static void ClearMaskMaterialCache()
- {
- foreach (var keyValuePair in MASK_MATERIALS_CACHE)
- {
- if(Application.isPlaying)
- Destroy(keyValuePair.Value);
- else
- DestroyImmediate(keyValuePair.Value);
- }
-
- MASK_MATERIALS_CACHE.Clear();
- }
-
- public Material GetModifiedMaterial(Material baseMaterial)
- {
- if (!shadow)
- return baseMaterial;
-
- shadow.ModifyShadowRendererMaterial(baseMaterial);
-
- if (!baseMaterial.HasProperty(ShaderId.COLOR_MASK) ||
- !baseMaterial.HasProperty(ShaderId.STENCIL_OP))
- return baseMaterial;
-
- bool casterIsMask = shadow.GetComponent<Mask>() != null;
-
- MASK_MATERIALS_CACHE.TryGetValue((casterIsMask, baseMaterial), out var mat);
-
- if (!mat)
- {
- mat = new Material(baseMaterial);
-
- if (shadow.ShadowAsSibling)
- {
- // Prevent shadow from writing to stencil mask
- mat.SetInt(ShaderId.COLOR_MASK, (int) ColorWriteMask.All);
- mat.SetInt(ShaderId.STENCIL_OP, (int) StencilOp.Keep);
- }
- else if (casterIsMask)
- {
- // Escape mask if we have one
- var baseStencilId = mat.GetInt(ShaderId.STENCIL_ID) + 1;
- int stencilDepth = 0;
- for (; stencilDepth < 8; stencilDepth++)
- {
- if (((baseStencilId >> stencilDepth) & 1) == 1)
- break;
- }
-
- stencilDepth = Mathf.Max(0, stencilDepth - 1);
- var stencilId = (1 << stencilDepth) - 1;
-
- mat.SetInt(ShaderId.STENCIL_ID, stencilId);
- mat.SetInt(ShaderId.STENCIL_READ_MASK, stencilId);
- }
-
- MASK_MATERIALS_CACHE[(casterIsMask, baseMaterial)] = mat;
- }
-
- return mat;
- }
- }
- }
|