205 lines
5.8 KiB
C#
205 lines
5.8 KiB
C#
using UnityEngine;
|
|
using UnityEngine.Rendering;
|
|
using UnityEngine.UI;
|
|
|
|
namespace JeffGrawAssets.FlexibleUI
|
|
{
|
|
[ExecuteAlways]
|
|
public class BlurredImage : Image, IBlur
|
|
{
|
|
#if UNITY_EDITOR
|
|
public static readonly string BlurCommonFieldName = nameof(_common);
|
|
public static readonly string AlphaBlendFieldName = nameof(_alphaBlend);
|
|
public static readonly string SourceImageFadeFieldName = nameof(_sourceImageFade);
|
|
#endif
|
|
|
|
private const string ImageShaderName = "Hidden/JeffGrawAssets/BlurredImage";
|
|
private static Shader _imageShader;
|
|
private static Shader ImageShader
|
|
{
|
|
get
|
|
{
|
|
if (!_imageShader)
|
|
_imageShader = Shader.Find(ImageShaderName);
|
|
return _imageShader;
|
|
}
|
|
}
|
|
|
|
private static readonly int BlurTexPropID = Shader.PropertyToID("_BlurTex");
|
|
|
|
private static Material _defaultBlurMaterial;
|
|
private static Material DefaultBlurMaterial
|
|
{
|
|
get
|
|
{
|
|
if (_defaultBlurMaterial == null)
|
|
_defaultBlurMaterial = new Material(ImageShader) { name = "DefaultBlurredImage" };
|
|
|
|
return _defaultBlurMaterial;
|
|
}
|
|
}
|
|
|
|
[SerializeField] private UIBlurCommon _common = new();
|
|
public UIBlurCommon Common => _common;
|
|
|
|
[SerializeField] [Range(0, 255)] private byte _alphaBlend = 255;
|
|
public byte AlphaBlend
|
|
{
|
|
get => _alphaBlend;
|
|
set
|
|
{
|
|
_alphaBlend = value;
|
|
SetVerticesDirty();
|
|
}
|
|
}
|
|
|
|
[SerializeField] [Range(0, 255)] private byte _sourceImageFade;
|
|
public byte SourceImageFade
|
|
{
|
|
get => _sourceImageFade;
|
|
set
|
|
{
|
|
_sourceImageFade = value;
|
|
SetVerticesDirty();
|
|
}
|
|
}
|
|
|
|
public float Alpha { get; private set; }
|
|
|
|
public float additionalBlurPadding;
|
|
public bool tryBatchWithSimilar;
|
|
public bool fillEntireRenderTexture;
|
|
public bool CanBatch => tryBatchWithSimilar && Common.blurPreset;
|
|
public bool FillEntireRenderTexture => CanBatch && fillEntireRenderTexture;
|
|
|
|
public bool ActiveAtZeroAlpha => false;
|
|
|
|
private RTHandle rtHandle;
|
|
|
|
protected override void OnEnable()
|
|
{
|
|
base.OnEnable();
|
|
Common.Init(this, FlexibleBlurFeature.ImageBasedBlurDict, FlexibleBlurFeature.ImageBasedLayersPerCameraDict);
|
|
Common.ValidateBlur();
|
|
FlexibleBlurPass.ComputeBlurEvent += Common.ComputeBlur;
|
|
}
|
|
|
|
protected override void OnDisable()
|
|
{
|
|
base.OnDisable();
|
|
Common.RemoveFromBlurList();
|
|
FlexibleBlurPass.ComputeBlurEvent -= Common.ComputeBlur;
|
|
}
|
|
|
|
#if UNITY_EDITOR
|
|
protected override void OnValidate()
|
|
{
|
|
base.OnValidate();
|
|
SetVerticesDirty();
|
|
Common.ValidateBlur();
|
|
}
|
|
#endif
|
|
|
|
private void ValidateCanvasShaderChannels()
|
|
{
|
|
if (!canvas)
|
|
return;
|
|
|
|
canvas.additionalShaderChannels |= AdditionalCanvasShaderChannels.TexCoord1;
|
|
}
|
|
|
|
void Update()
|
|
{
|
|
CalculateBlur();
|
|
}
|
|
|
|
void LateUpdate()
|
|
{
|
|
if (!canvas || !canvas.isActiveAndEnabled)
|
|
return;
|
|
|
|
material = DefaultBlurMaterial;
|
|
|
|
var key = Common.GetCameraFeatureKey(canvas);
|
|
if (!key.camera || !FlexibleBlurPass.TryGetImageMaterial(key.camera, key.featureNumber, Common.LayerRank, ImageShader, out var mat))
|
|
return;
|
|
|
|
if (material != mat)
|
|
{
|
|
material = mat;
|
|
SetMaterialDirty();
|
|
}
|
|
else if (!rtHandle?.rt)
|
|
{
|
|
SetMaterialDirty();
|
|
}
|
|
}
|
|
|
|
private void CalculateBlur()
|
|
{
|
|
if (canvasRenderer.cull || !canvas || !canvas.isActiveAndEnabled)
|
|
{
|
|
Common.RemoveFromBlurList();
|
|
return;
|
|
}
|
|
|
|
var canvasAlpha = canvasRenderer.GetInheritedAlpha();
|
|
if (canvasAlpha == 0 || color.a == 0)
|
|
{
|
|
Common.RemoveFromBlurList();
|
|
return;
|
|
}
|
|
|
|
Alpha = Mathf.Lerp(canvasAlpha * color.a, 1f, AlphaBlend / 255f) * Common.blurStrength;
|
|
|
|
Common.CacheBlur(canvas, rectTransform, Vector2.zero, 0f, false, Vector2.zero, additionalBlurPadding, fillWholeScreen: fillEntireRenderTexture);
|
|
Common.ComputeBlurCommon(canvas, rectTransform, Vector2.zero, 0f, false, Vector2.zero, additionalBlurPadding, fillWholeScreen: fillEntireRenderTexture);
|
|
}
|
|
|
|
public override Material materialForRendering
|
|
{
|
|
get
|
|
{
|
|
if (!canvas || !canvas.isActiveAndEnabled)
|
|
return DefaultBlurMaterial;
|
|
|
|
var key = Common.GetCameraFeatureKey(canvas);
|
|
if (!key.camera)
|
|
return DefaultBlurMaterial;
|
|
|
|
if (!FlexibleBlurPass.TryGetImageRT(key.camera, key.featureNumber, Common.LayerRank, out var newHandle))
|
|
return null;
|
|
|
|
var mat = base.materialForRendering;
|
|
if (mat != null)
|
|
mat.SetTexture(BlurTexPropID, rtHandle = newHandle);
|
|
|
|
return mat;
|
|
}
|
|
}
|
|
|
|
protected override void OnPopulateMesh(VertexHelper vh)
|
|
{
|
|
ValidateCanvasShaderChannels();
|
|
|
|
if (sprite == null && type == Type.Filled)
|
|
FilledMeshHelper.GenerateFilledMesh(vh, this);
|
|
else
|
|
base.OnPopulateMesh(vh);
|
|
|
|
var sourceImageFadeNormalized = SourceImageFade / 255f;
|
|
var alphaBlendNormalized = AlphaBlend / 255f;
|
|
var vertices = UnityEngine.Pool.ListPool<UIVertex>.Get();
|
|
vh.GetUIVertexStream(vertices);
|
|
for (int i = 0; i < vertices.Count; i++)
|
|
{
|
|
var vertex = vertices[i];
|
|
vertex.uv0 = new Vector4(vertex.uv0.x, vertex.uv0.y, sourceImageFadeNormalized, alphaBlendNormalized);
|
|
vertices[i] = vertex;
|
|
}
|
|
vh.Clear();
|
|
vh.AddUIVertexTriangleStream(vertices);
|
|
UnityEngine.Pool.ListPool<UIVertex>.Release(vertices);
|
|
}
|
|
}
|
|
} |