524 lines
21 KiB
C#
524 lines
21 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEngine.XR;
|
|
|
|
namespace JeffGrawAssets.FlexibleUI
|
|
{
|
|
[Serializable]
|
|
public class UIBlurCommon
|
|
{
|
|
public enum BlurReferencesFrom { Self, ReferenceProvider }
|
|
|
|
public BlurReferencesFrom blurReferencesFrom = BlurReferencesFrom.Self;
|
|
public Camera cameraReference;
|
|
public int featureNumber;
|
|
|
|
[Range(0, 1)] public float blurStrength = 1f;
|
|
public int unrankedLayer;
|
|
public int priority;
|
|
|
|
public BlurPreset blurPreset;
|
|
public BlurSettings blurInstanceSettings = new();
|
|
|
|
private BlurSettings _activeSettings;
|
|
public BlurSettings ActiveSettings => _activeSettings;
|
|
|
|
public Camera WorldCamera { get; private set; }
|
|
|
|
public Vector4 BlurRegion { get; private set; }
|
|
public Vector4 BlurRegionRight { get; private set; }
|
|
|
|
public Matrix4x4 TransformationMatrix { get; private set; }
|
|
|
|
public int LayerRank { get; private set; }
|
|
public bool PresentInBlurList { get; private set; }
|
|
public bool IsAngled { get; private set; }
|
|
|
|
private IBlur blur;
|
|
private Dictionary<(Camera camera, int featureNumber), List<IBlur>> blurDict;
|
|
private Dictionary<(Camera camera, int featureNumber), int> layersPerCameraDict;
|
|
|
|
public readonly Vector3[] worldCorners = new Vector3[4];
|
|
private readonly Vector3[] blitRegionCornersArray = new Vector3[4];
|
|
|
|
public Vector4[] ScreenCorners { get; } = new Vector4[4];
|
|
public Vector4[] ScreenCornersRight { get; } = new Vector4[4];
|
|
private readonly Vector4[] prevScreenCorners = new Vector4[4];
|
|
|
|
private static readonly Vector4 TransformationMatrixColumn2 = new (0f, 0f, 1f, 0f);
|
|
|
|
private (Camera prevCamera, int prevFeatureNumber) prevKey;
|
|
private bool hasVisiblePixels, hasVisiblePixelsRight;
|
|
public bool HasVisiblePixels(bool right = false) => right ? hasVisiblePixelsRight : hasVisiblePixels;
|
|
|
|
private Vector2 xrScale;
|
|
private bool useXR;
|
|
private int prevPriority, prevUnrankedLayer;
|
|
private float minX, maxX, minY, maxY, minXRight, maxXRight, minYRight, maxYRight;
|
|
public float MinX(bool right = false) => right ? minXRight : minX;
|
|
public float MaxX(bool right = false) => right ? maxXRight : maxX;
|
|
public float MinY(bool right = false) => right ? minYRight : minY;
|
|
public float MaxY(bool right = false) => right ? maxYRight : maxY;
|
|
|
|
private bool hasCachedBlur;
|
|
private Canvas cachedCanvas;
|
|
private RectTransform cachedRectTransform;
|
|
private Vector2 cachedOffset, cachedShapePadding;
|
|
private float cachedRotation, cachedBlurPadding;
|
|
private bool cachedUseFilterPadding, cachedFitRotatedImageWithinBounds, cachedFillWholeScreen;
|
|
|
|
public void Init(IBlur blur, Dictionary<(Camera, int), List<IBlur>> blurDict, Dictionary<(Camera, int), int> layersPerCamera) => (this.blur, this.blurDict, this.layersPerCameraDict) = (blur, blurDict, layersPerCamera);
|
|
|
|
public void CopyPresetToInstanceSettings()
|
|
{
|
|
if (blurPreset == null)
|
|
{
|
|
Debug.LogWarning("Cannot copy from the preset, because no preset has been assigned!");
|
|
return;
|
|
}
|
|
|
|
blurInstanceSettings.CopySettings(blurPreset.Settings[QualitySettings.GetQualityLevel()]);
|
|
}
|
|
|
|
public void ValidateBlur()
|
|
{
|
|
if (blurPreset == null)
|
|
{
|
|
_activeSettings = blurInstanceSettings;
|
|
}
|
|
else
|
|
{
|
|
var qualityLvl = QualitySettings.GetQualityLevel();
|
|
_activeSettings = blurPreset.Settings.Count > qualityLvl
|
|
? blurPreset.Settings[qualityLvl]
|
|
: blurPreset.Settings[^1];
|
|
}
|
|
}
|
|
|
|
public void PlaceInBlurList((Camera camera, int featureNumber) key)
|
|
{
|
|
if (blur is UIBlur && blur.Alpha == 0 && !blur.ActiveAtZeroAlpha)
|
|
return;
|
|
|
|
if (!blurDict.TryGetValue(key, out var blurList))
|
|
blurList = blurDict[key] = new List<IBlur>();
|
|
|
|
if (blurList.Count == 0)
|
|
{
|
|
if (!layersPerCameraDict.TryAdd(key, 1))
|
|
layersPerCameraDict[key] += 1;
|
|
|
|
blurList.Add(blur);
|
|
LayerRank = 0;
|
|
prevKey = key;
|
|
prevPriority = priority;
|
|
prevUnrankedLayer = unrankedLayer;
|
|
PresentInBlurList = true;
|
|
return;
|
|
}
|
|
|
|
var idx = 0;
|
|
var currentUnrankedLayer = blurList[0].Common.prevUnrankedLayer;
|
|
var currentLayerRank = 0;
|
|
|
|
for (; idx < blurList.Count; idx++)
|
|
{
|
|
var otherUnrankedLayer = blurList[idx].Common.prevUnrankedLayer;
|
|
|
|
if (currentUnrankedLayer != otherUnrankedLayer)
|
|
{
|
|
currentUnrankedLayer = otherUnrankedLayer;
|
|
currentLayerRank++;
|
|
}
|
|
|
|
if (unrankedLayer <= otherUnrankedLayer)
|
|
break;
|
|
}
|
|
|
|
if (unrankedLayer == currentUnrankedLayer)
|
|
{
|
|
for (; idx < blurList.Count; idx++)
|
|
{
|
|
var otherBlur = blurList[idx];
|
|
if (priority < otherBlur.Priority || unrankedLayer < otherBlur.Common.prevUnrankedLayer)
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (idx == blurList.Count)
|
|
currentLayerRank++;
|
|
|
|
if (!layersPerCameraDict.TryAdd(key, 1))
|
|
layersPerCameraDict[key] += 1;
|
|
|
|
for (int i = idx; i < blurList.Count; i++)
|
|
blurList[i].Common.LayerRank++;
|
|
}
|
|
|
|
blurList.Insert(idx, blur);
|
|
LayerRank = currentLayerRank;
|
|
prevKey = key;
|
|
prevPriority = priority;
|
|
prevUnrankedLayer = unrankedLayer;
|
|
PresentInBlurList = true;
|
|
}
|
|
|
|
public void RemoveFromBlurList()
|
|
{
|
|
hasCachedBlur = false;
|
|
|
|
if (!PresentInBlurList || !blurDict.TryGetValue(prevKey, out var blurList))
|
|
{
|
|
prevKey = (null, 0);
|
|
PresentInBlurList = false;
|
|
return;
|
|
}
|
|
|
|
var idx = blurList.IndexOf(blur);
|
|
blurList.RemoveAt(idx);
|
|
|
|
var prevElementSharesLayer = idx > 0 && blurList[idx - 1].Common.LayerRank == LayerRank;
|
|
var nextElementSharesLayer = idx < blurList.Count && blurList[idx].Common.LayerRank == LayerRank;
|
|
var layerRemoved = !prevElementSharesLayer && !nextElementSharesLayer;
|
|
if (!layerRemoved)
|
|
{
|
|
prevKey = (null, 0);
|
|
PresentInBlurList = false;
|
|
return;
|
|
}
|
|
|
|
if (blurList.Count == 0)
|
|
blurDict.Remove(prevKey);
|
|
else for (int i = idx; i < blurList.Count; i++)
|
|
blurList[i].Common.LayerRank--;
|
|
|
|
var cameraLayers = --layersPerCameraDict[prevKey];
|
|
if (cameraLayers == 0)
|
|
layersPerCameraDict.Remove(prevKey);
|
|
|
|
prevKey = (null, 0);
|
|
PresentInBlurList = false;
|
|
}
|
|
|
|
public (Camera camera, int featureNumber) GetCameraFeatureKey(Canvas canvas)
|
|
{
|
|
if (blurReferencesFrom == BlurReferencesFrom.ReferenceProvider && BlurReferenceProvider.CameraReferenceDict.TryGetValue(canvas, out var result) && result.camera != null)
|
|
return result;
|
|
|
|
return cameraReference ? (cameraReference, featureIndex: featureNumber) : (Camera.main, featureIndex: featureNumber);
|
|
}
|
|
|
|
bool TryGetIntersection(Plane plane, Vector3 point1, Vector3 point2, out Vector3 intersection)
|
|
{
|
|
var lineDirection = point2 - point1;
|
|
var ray = new Ray(point1, lineDirection.normalized);
|
|
|
|
if (plane.Raycast(ray, out var enter))
|
|
{
|
|
intersection = point1 + enter * lineDirection.normalized;
|
|
return true;
|
|
}
|
|
|
|
intersection = Vector3.zero;
|
|
return false;
|
|
}
|
|
|
|
private void GetScaledWorldCorners(RectTransform rectTransform, Vector2 offset, float rotation, bool fitRotationInsideOriginalBounds, Vector2 shapePadding, float blurPadding, Vector3[] worldCornersArray)
|
|
{
|
|
rectTransform.GetLocalCorners(blitRegionCornersArray);
|
|
var (rectWidth, rectHeight) = (rectTransform.rect.width, rectTransform.rect.height);
|
|
var rotationQuat = Quaternion.Euler(0, 0, rotation);
|
|
var shapePaddingFactor = new Vector3((rectWidth + shapePadding.x) / rectWidth, (rectHeight + shapePadding.y) / rectHeight, 1);
|
|
var totalPaddingFactor = new Vector3((rectWidth + shapePadding.x + blurPadding) / rectWidth, (rectHeight + shapePadding.y + blurPadding) / rectHeight, 1);
|
|
var pivotAdjust = new Vector3(rectWidth* (0.5f - rectTransform.pivot.x), rectHeight * (0.5f - rectTransform.pivot.y), 0);
|
|
|
|
// fitRotationInsideOriginalBounds scales the rotated image so that it fits inside the bounds of the non-rotated image.
|
|
float scaleFactor = 1f;
|
|
if (fitRotationInsideOriginalBounds && rotation != 0f)
|
|
{
|
|
var angleRad = rotation * Mathf.Deg2Rad;
|
|
var cosTheta = Mathf.Abs(Mathf.Cos(angleRad));
|
|
var sinTheta = Mathf.Abs(Mathf.Sin(angleRad));
|
|
var scaleX = rectWidth / (rectWidth * cosTheta + rectHeight * sinTheta);
|
|
var scaleY = rectHeight / (rectWidth * sinTheta + rectHeight * cosTheta);
|
|
scaleFactor = Mathf.Min(scaleX, scaleY);
|
|
}
|
|
|
|
var localToWorldMatrix = rectTransform.localToWorldMatrix;
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
var localCorner = blitRegionCornersArray[i];
|
|
localCorner -= pivotAdjust;
|
|
|
|
var paddedBlurCorner = Vector3.Scale(localCorner, totalPaddingFactor);
|
|
paddedBlurCorner = rotationQuat * paddedBlurCorner * scaleFactor;
|
|
paddedBlurCorner += (Vector3)offset;
|
|
paddedBlurCorner += pivotAdjust;
|
|
worldCornersArray[i] = localToWorldMatrix.MultiplyPoint(paddedBlurCorner);
|
|
|
|
var paddedBlitCorner = Vector3.Scale(localCorner, shapePaddingFactor);
|
|
paddedBlitCorner = rotationQuat * paddedBlitCorner * scaleFactor;
|
|
paddedBlitCorner += (Vector3)offset;
|
|
paddedBlitCorner += pivotAdjust;
|
|
blitRegionCornersArray[i] = localToWorldMatrix.MultiplyPoint(paddedBlitCorner);
|
|
}
|
|
|
|
var worldCenter = (blitRegionCornersArray[0] + blitRegionCornersArray[1] + blitRegionCornersArray[2] + blitRegionCornersArray[3]) * 0.25f;
|
|
var deltaQ1 = (blitRegionCornersArray[3] - blitRegionCornersArray[0]) * 0.5f;
|
|
var deltaQ2 = (blitRegionCornersArray[1] - blitRegionCornersArray[0]) * 0.5f;
|
|
var transformationMatrix = new Matrix4x4();
|
|
|
|
transformationMatrix.SetColumn(0, new Vector4(deltaQ1.x, deltaQ1.y, deltaQ1.z, 0f));
|
|
transformationMatrix.SetColumn(1, new Vector4(deltaQ2.x, deltaQ2.y, deltaQ2.z, 0f));
|
|
transformationMatrix.SetColumn(2, TransformationMatrixColumn2);
|
|
transformationMatrix.SetColumn(3, new Vector4(worldCenter.x, worldCenter.y, worldCenter.z, 1f));
|
|
TransformationMatrix = transformationMatrix;
|
|
}
|
|
|
|
public void CacheBlur(Canvas canvas, RectTransform rectTransform, Vector2 offset, float rotation, bool fitRotatedImageWithinBounds, Vector2 shapePadding, float blurPadding = 0f, bool useFilterPadding = true, bool fillWholeScreen = false)
|
|
{
|
|
(cachedCanvas, cachedRectTransform, cachedOffset, cachedRotation, cachedFitRotatedImageWithinBounds, cachedShapePadding, cachedBlurPadding, cachedUseFilterPadding, cachedFillWholeScreen) = (canvas, rectTransform, offset, rotation, fitRotatedImageWithinBounds, shapePadding, blurPadding, useFilterPadding, fillWholeScreen);
|
|
hasCachedBlur = true;
|
|
}
|
|
|
|
public void ComputeBlur(float filteringPadding)
|
|
{
|
|
if (!hasCachedBlur)
|
|
return;
|
|
|
|
ComputeBlurCommon(cachedCanvas, cachedRectTransform, cachedOffset, cachedRotation, cachedFitRotatedImageWithinBounds, cachedShapePadding, cachedBlurPadding, cachedUseFilterPadding ? filteringPadding : 0f, cachedFillWholeScreen);
|
|
hasCachedBlur = false;
|
|
}
|
|
|
|
public void ComputeBlurCommon(Canvas canvas, RectTransform rectTransform, Vector2 offset, float rotation, bool fitRotationInsideOriginalBounds, Vector2 shapePadding, float blurPadding = 0f, float filteringPadding = 0f, bool fillWholeScreen = false)
|
|
{
|
|
var key = GetCameraFeatureKey(canvas);
|
|
var camera = key.camera;
|
|
|
|
if (!camera || !canvas || !canvas.isActiveAndEnabled || !rectTransform.gameObject.activeInHierarchy)
|
|
{
|
|
RemoveFromBlurList();
|
|
return;
|
|
}
|
|
if (PresentInBlurList && (key != prevKey || priority != prevPriority || unrankedLayer != prevUnrankedLayer))
|
|
{
|
|
RemoveFromBlurList();
|
|
PlaceInBlurList(key);
|
|
}
|
|
|
|
if (fillWholeScreen)
|
|
{
|
|
if (!PresentInBlurList)
|
|
PlaceInBlurList(key);
|
|
|
|
return;
|
|
}
|
|
|
|
blurPadding = (blurPadding + filteringPadding) / canvas.scaleFactor;
|
|
shapePadding = (shapePadding + new Vector2(filteringPadding, filteringPadding)) / canvas.scaleFactor;
|
|
|
|
if (canvas.renderMode == RenderMode.ScreenSpaceCamera)
|
|
WorldCamera = canvas.worldCamera;
|
|
else if (canvas.renderMode == RenderMode.WorldSpace)
|
|
WorldCamera = canvas.worldCamera ?? key.camera;
|
|
else
|
|
WorldCamera = null;
|
|
|
|
if (blurPreset)
|
|
_activeSettings = blurPreset.Settings[blurPreset.preview >= 0 ? blurPreset.preview : QualitySettings.GetQualityLevel()];
|
|
|
|
GetScaledWorldCorners(rectTransform, offset, rotation, fitRotationInsideOriginalBounds, shapePadding, blurPadding, worldCorners);
|
|
|
|
var canvasCamera = WorldCamera ?? key.camera;
|
|
|
|
#if XR_MANAGEMENT_INSTALLED
|
|
useXR = XRSettings.enabled && canvasCamera.stereoTargetEye == StereoTargetEyeMask.Both;
|
|
var xrScale = useXR ? new((float)XRSettings.eyeTextureWidth / canvasCamera.pixelWidth, (float)XRSettings.eyeTextureHeight / canvasCamera.pixelHeight) : Vector2.one;
|
|
#else
|
|
useXR = false;
|
|
var xrScale = Vector2.one;
|
|
#endif
|
|
|
|
var cameraRectOffset = new Vector3(-canvasCamera.pixelRect.x, -canvasCamera.pixelRect.y);
|
|
var cornersChanged = false;
|
|
|
|
if (canvas.renderMode == RenderMode.ScreenSpaceOverlay)
|
|
{
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
var vp = canvasCamera.ScreenToViewportPoint(worldCorners[i]);
|
|
ScreenCorners[i] = canvasCamera.ViewportToScreenPoint(vp) + cameraRectOffset;
|
|
if (prevScreenCorners[i] == ScreenCorners[i])
|
|
continue;
|
|
|
|
prevScreenCorners[i] = ScreenCorners[i];
|
|
cornersChanged = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
var hasVerticesInFrontOfCamera = false;
|
|
var camPlane = new Plane(canvasCamera.transform.forward, canvasCamera.transform.position);
|
|
const float vertexEpsilon = 1e-5f;
|
|
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
var dot = Vector3.Dot(canvasCamera.transform.forward, canvasCamera.transform.position - worldCorners[i]);
|
|
if (dot < 0)
|
|
{
|
|
hasVerticesInFrontOfCamera = true;
|
|
continue;
|
|
}
|
|
|
|
var leftIdx = (int)Mathf.Repeat(i - 1, 4);
|
|
var rightIdx = (int)Mathf.Repeat(i + 1, 4);
|
|
bool hasLeftIntersect = TryGetIntersection(camPlane, worldCorners[i], worldCorners[leftIdx], out var intersect);
|
|
bool hasRightIntersect = TryGetIntersection(camPlane, worldCorners[i], worldCorners[rightIdx], out var otherIntersect);
|
|
if (hasLeftIntersect && hasRightIntersect)
|
|
{
|
|
var leftDot = Vector3.Dot((worldCorners[i] - worldCorners[leftIdx]).normalized, canvasCamera.transform.forward);
|
|
var rightDot = Vector3.Dot((worldCorners[i] - worldCorners[rightIdx]).normalized, canvasCamera.transform.forward);
|
|
worldCorners[i] = camPlane.normal * vertexEpsilon + (leftDot < rightDot ? intersect : otherIntersect);
|
|
}
|
|
else if (hasLeftIntersect)
|
|
{
|
|
worldCorners[i] = camPlane.normal * vertexEpsilon + intersect;
|
|
}
|
|
else if (hasRightIntersect)
|
|
{
|
|
worldCorners[i] = camPlane.normal * vertexEpsilon + otherIntersect;
|
|
}
|
|
else if (TryGetIntersection(camPlane, worldCorners[i], worldCorners[(int)Mathf.Repeat(i + 2, 4)], out intersect))
|
|
{
|
|
worldCorners[i] = camPlane.normal * vertexEpsilon + intersect;
|
|
}
|
|
}
|
|
|
|
if (!hasVerticesInFrontOfCamera)
|
|
{
|
|
RemoveFromBlurList();
|
|
return;
|
|
}
|
|
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
if (useXR)
|
|
{
|
|
ScreenCorners[i] = xrScale * (canvasCamera.WorldToScreenPoint(worldCorners[i], Camera.MonoOrStereoscopicEye.Left) + cameraRectOffset);
|
|
ScreenCornersRight[i] = xrScale * (canvasCamera.WorldToScreenPoint(worldCorners[i], Camera.MonoOrStereoscopicEye.Right) + cameraRectOffset);
|
|
}
|
|
else
|
|
{
|
|
ScreenCorners[i] = canvasCamera.WorldToScreenPoint(worldCorners[i]) + cameraRectOffset;
|
|
}
|
|
|
|
if (prevScreenCorners[i] == ScreenCorners[i])
|
|
continue;
|
|
|
|
prevScreenCorners[i] = ScreenCorners[i];
|
|
cornersChanged = true;
|
|
}
|
|
}
|
|
|
|
if (!cornersChanged)
|
|
{
|
|
if ((hasVisiblePixels || hasVisiblePixelsRight) && !PresentInBlurList)
|
|
PlaceInBlurList(key);
|
|
|
|
return;
|
|
}
|
|
|
|
#if XR_MANAGEMENT_INSTALLED
|
|
var pixelWidth = useXR ? XRSettings.eyeTextureWidth : canvasCamera.pixelWidth;
|
|
var pixelHeight = useXR ? XRSettings.eyeTextureHeight : canvasCamera.pixelHeight;
|
|
#else
|
|
var pixelWidth = canvasCamera.pixelWidth;
|
|
var pixelHeight = canvasCamera.pixelHeight;
|
|
#endif
|
|
|
|
minX = minY = float.PositiveInfinity;
|
|
maxX = maxY = float.NegativeInfinity;
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
var point = ScreenCorners[i];
|
|
minX = Mathf.Min(point.x, minX);
|
|
minY = Mathf.Min(point.y, minY);
|
|
maxX = Mathf.Max(point.x, maxX);
|
|
maxY = Mathf.Max(point.y, maxY);
|
|
}
|
|
|
|
minX = Mathf.Max(minX, 0);
|
|
maxX = Mathf.Min(maxX, pixelWidth);
|
|
minY = Mathf.Max(minY, 0);
|
|
maxY = Mathf.Min(maxY, pixelHeight);
|
|
|
|
hasVisiblePixels = maxX > 0 && maxY > 0 && minX < pixelWidth && minY < pixelHeight && maxX - minX > 0 && maxY - minY > 0;
|
|
|
|
if (useXR)
|
|
{
|
|
minXRight = minYRight = float.PositiveInfinity;
|
|
maxXRight = maxYRight = float.NegativeInfinity;
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
var point = ScreenCornersRight[i];
|
|
minXRight = Mathf.Min(point.x, minXRight);
|
|
minYRight = Mathf.Min(point.y, minYRight);
|
|
maxXRight = Mathf.Max(point.x, maxXRight);
|
|
maxYRight = Mathf.Max(point.y, maxYRight);
|
|
}
|
|
|
|
minXRight = Mathf.Max(minXRight, 0);
|
|
maxXRight = Mathf.Min(maxXRight, pixelWidth);
|
|
minYRight = Mathf.Max(minYRight, 0);
|
|
maxYRight = Mathf.Min(maxYRight, pixelHeight);
|
|
|
|
hasVisiblePixelsRight = maxXRight > 0 && maxYRight > 0 && minXRight < pixelWidth && minYRight < pixelHeight && maxXRight - minXRight > 0 && maxYRight - minYRight > 0;
|
|
}
|
|
else
|
|
{
|
|
hasVisiblePixelsRight = false;
|
|
}
|
|
|
|
switch (hasVisiblePixels || hasVisiblePixelsRight)
|
|
{
|
|
case true when !PresentInBlurList:
|
|
PlaceInBlurList(key);
|
|
break;
|
|
case false when PresentInBlurList:
|
|
RemoveFromBlurList();
|
|
break;
|
|
}
|
|
|
|
if (!hasVisiblePixels && !hasVisiblePixelsRight)
|
|
return;
|
|
|
|
const float epsilon = 1e-4f;
|
|
IsAngled = useXR ||
|
|
Math.Abs(ScreenCorners[0].x - ScreenCorners[1].x) > epsilon ||
|
|
Math.Abs(ScreenCorners[1].y - ScreenCorners[2].y) > epsilon ||
|
|
Math.Abs(ScreenCorners[2].x - ScreenCorners[3].x) > epsilon ||
|
|
Math.Abs(ScreenCorners[3].y - ScreenCorners[0].y) > epsilon;
|
|
|
|
prevKey = key;
|
|
BlurRegion = ComputeBlurRegion(minX, minY, maxX, maxY);
|
|
if (useXR)
|
|
BlurRegionRight = ComputeBlurRegion(minXRight, minYRight, maxXRight, maxYRight);
|
|
}
|
|
|
|
public static Vector4 ComputeBlurRegion(float minX, float minY, float maxX, float maxY)
|
|
{
|
|
var (intMinX, intMinY, intMaxX, intMaxY) = (Mathf.RoundToInt(minX), Mathf.RoundToInt(minY), Mathf.RoundToInt(maxX), Mathf.RoundToInt(maxY));
|
|
var blurRegion = new Vector4(intMinX, intMinY, intMaxX - intMinX, intMaxY - intMinY);
|
|
return blurRegion;
|
|
}
|
|
|
|
public Vector4 ComputeBlurRegion(float renderScale = 1f)
|
|
{
|
|
var (intMinX, intMinY, intMaxX, intMaxY) = (Mathf.RoundToInt(minX * renderScale), Mathf.RoundToInt(minY * renderScale), Mathf.RoundToInt(maxX * renderScale), Mathf.RoundToInt(maxY * renderScale));
|
|
var blurRegion = new Vector4(intMinX, intMinY, intMaxX - intMinX, intMaxY - intMinY);
|
|
return blurRegion;
|
|
}
|
|
}
|
|
} |