Files
Cielonos/Assets/Plugins/FlexibleUI/FlexibleBlur/Scripts/FlexibleBlurRenderGraph.cs
SoulliesOfficial 72756712f7 UI调整
2026-05-27 15:15:28 -04:00

804 lines
38 KiB
C#

#if UNITY_2023_3_OR_NEWER
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Rendering;
using UnityEngine.Rendering.RenderGraphModule;
using UnityEngine.Rendering.Universal;
using UnityEngine.XR;
namespace JeffGrawAssets.FlexibleUI
{
public partial class FlexibleBlurPass
{
class BlurPassData
{
public PooledListDictionary<(BlurSettings blurSettings, float alpha), List<IBlur>, IBlur> batchedBlurs;
public TextureHandle source;
public TextureHandle temporaryUIBlurFullScreenHandle;
public List<TextureHandle> instanceHandles = new();
public List<TextureHandle> textureHandles = new();
public List<(int width, int height)> textureDimensions = new();
public Queue<int> textureIndices = new();
public List<IBlur> blurAreas, blurredImageAreas;
public Camera camera;
public int featureIdx;
public float renderScale, originalWidth, originalHeight;
public bool singlePassVR, multiPassVR, rightEye, haveUIBlurAreas, haveBlurredImageAreas, blurredImageLayersSeeLower, blurredImageSeeUIBlurs, uiBlurLayersSeeLower, useComputeShaders, overlayCompatibilityFix;
}
public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
{
if (!blurLayerAdddedThisFrame && (IndividuallyPaused || FlexibleBlurFeature.GloballyPaused))
return;
blurLayerAdddedThisFrame = false;
var cameraData = frameData.Get<UniversalCameraData>();
if (cameraData.isPreviewCamera || cameraData.isSceneViewCamera)
return;
var camera = cameraData.camera;
var key = (camera, featureIdx);
SharedSetup(camera.pixelWidth, camera.pixelHeight, cameraData.renderScale);
UIBlur.BlurDict.TryGetValue(key, out var blurAreas);
FlexibleBlurFeature.ImageBasedBlurDict.TryGetValue(key, out var blurredImageAreas);
var haveUIBlurAreas = blurAreas is { Count: > 0 };
var haveBlurredImageAreas = blurredImageAreas is { Count: > 0 };
Setup(cameraData.camera, cameraData.cameraTargetDescriptor);
if (!haveUIBlurAreas && !haveBlurredImageAreas)
return;
var textureDescriptor = cameraData.cameraTargetDescriptor;
textureDescriptor.enableRandomWrite = useComputeShaders;
textureDescriptor.msaaSamples = 1;
textureDescriptor.depthStencilFormat = GraphicsFormat.None;
textureDescriptor.graphicsFormat = blurGraphicsFormat;
var (originalWidth, originalHeight) = (textureDescriptor.width, textureDescriptor.height);
var renderScale = cameraData.renderScale;
#if XR_MANAGEMENT_INSTALLED
var singlePassVR = XRSettings.enabled && XRSettings.stereoRenderingMode >= XRSettings.StereoRenderingMode.SinglePassInstanced;
var rightEye = XRSettings.enabled && cameraData.xr.multipassId == 1;
#else
var (rightEye, singlePassVR) = (false, false);
#endif
using var builder = renderGraph.AddUnsafePass<BlurPassData>(ProfilerTag, out var passData);
(passData.camera, passData.featureIdx, passData.renderScale, passData.originalWidth, passData.originalHeight, passData.singlePassVR, passData.haveUIBlurAreas, passData.haveBlurredImageAreas, passData.blurAreas, passData.blurredImageAreas, passData.batchedBlurs, passData.blurredImageSeeUIBlurs, passData.blurredImageLayersSeeLower, passData.uiBlurLayersSeeLower, passData.useComputeShaders, passData.overlayCompatibilityFix) =
( camera, featureIdx, renderScale, originalWidth, originalHeight, singlePassVR, haveUIBlurAreas, haveBlurredImageAreas, blurAreas, blurredImageAreas, batchedBlurs, blurredImageSeeUIBlurs, blurredImageLayersSeeLower, uiBlurLayersSeeLower, useComputeShaders, overlayCompatibilityFix);
#if XR_MANAGEMENT_INSTALLED
passData.multiPassVR = XRSettings.enabled && XRSettings.stereoRenderingMode == XRSettings.StereoRenderingMode.MultiPass;
#else
passData.multiPassVR = false;
#endif
passData.textureIndices.Clear();
passData.textureHandles.Clear();
passData.textureDimensions.Clear();
passData.instanceHandles.Clear();
passData.source = frameData.Get<UniversalResourceData>().activeColorTexture;
builder.UseTexture(passData.source, AccessFlags.ReadWrite);
foreach (var rtHandle in currentRTHandleList)
{
var texture = renderGraph.ImportTexture(rtHandle);
passData.instanceHandles.Add(texture);
builder.UseTexture(texture);
}
if (blurredImageSeeUIBlurs)
{
HandleUIBlurs();
HandleBlurredImages();
}
else
{
HandleBlurredImages();
HandleUIBlurs(haveBlurredImageAreas);
}
builder.SetRenderFunc(static(BlurPassData data, UnsafeGraphContext context) => Pass(data, context));
void HandleUIBlurs(bool useTempRT = false)
{
if (!haveUIBlurAreas)
return;
if (useTempRT)
{
textureDescriptor.width = originalWidth;
textureDescriptor.height = originalHeight;
passData.temporaryUIBlurFullScreenHandle = UniversalRenderer.CreateRenderGraphTexture(renderGraph, textureDescriptor, nameof(BlurPassData.temporaryUIBlurFullScreenHandle), false, FilterMode.Bilinear);
builder.UseTexture(passData.temporaryUIBlurFullScreenHandle);
}
foreach (var blurArea in blurAreas)
AddTemporaryTextures(blurArea.Settings, rightEye ? blurArea.Common.BlurRegionRight : blurArea.Common.BlurRegion, blurArea.Alpha);
}
void HandleBlurredImages()
{
if (!haveBlurredImageAreas)
return;
int currentLayer = blurredImageAreas[0].Layer;
int currentPriority = blurredImageAreas[0].Priority;
foreach (var blurImage in blurredImageAreas)
{
if (blurImage.Layer > currentLayer || blurImage.Priority > currentPriority)
{
TryApplyBatchedBlurs();
currentLayer = blurImage.Layer;
currentPriority = blurImage.Priority;
}
if (blurImage.CanBatch)
batchedBlurs.Add((blurImage.Settings, blurImage.Alpha), blurImage);
else
AddTemporaryTextures(blurImage.Settings, rightEye ? blurImage.Common.BlurRegionRight : blurImage.Common.BlurRegion, blurImage.Alpha);
}
TryApplyBatchedBlurs();
void TryApplyBatchedBlurs()
{
foreach (var kvp in batchedBlurs)
{
var fillEntireRenderTexture = false;
foreach (var blur in kvp.Value)
{
if (!blur.FillEntireRenderTexture)
continue;
fillEntireRenderTexture = true;
break;
}
if (!fillEntireRenderTexture && kvp.Value.Count == 1)
{
var blurImage = kvp.Value[0];
AddTemporaryTextures(blurImage.Settings, rightEye ? blurImage.Common.BlurRegionRight : blurImage.Common.BlurRegion, blurImage.Alpha);
continue;
}
float minX, minY, maxX, maxY;
if (fillEntireRenderTexture)
{
(minX, minY, maxX, maxY) = (0, 0, originalWidth, originalHeight);
}
else
{
(minX, minY, maxX, maxY) = (float.PositiveInfinity, float.PositiveInfinity, float.NegativeInfinity, float.NegativeInfinity);
foreach (var batchedBlur in kvp.Value)
{
minX = Math.Min(minX, batchedBlur.MinX(rightEye));
minY = Math.Min(minY, batchedBlur.MinY(rightEye));
maxX = Math.Max(maxX, batchedBlur.MaxX(rightEye));
maxY = Math.Max(maxY, batchedBlur.MaxY(rightEye));
if (!singlePassVR)
continue;
minX = Math.Min(minX, batchedBlur.MinX(true));
minY = Math.Min(minY, batchedBlur.MinY(true));
maxX = Math.Max(maxX, batchedBlur.MaxX(true));
maxY = Math.Max(maxY, batchedBlur.MaxY(true));
}
}
var blurRegion = UIBlurCommon.ComputeBlurRegion(minX, minY, maxX, maxY);
var settings = kvp.Key.blurSettings;
AddTemporaryTextures(settings, blurRegion, kvp.Key.alpha);
}
batchedBlurs.Clear();
}
}
void AddTemporaryTextures(BlurSettings settings, Vector4 blurRegion, float alpha)
{
blurRegion *= renderScale;
var handles = passData.textureHandles;
var dimensions = passData.textureDimensions;
var indices = passData.textureIndices;
var currentTextureIdx = 0;
var aspect = blurRegion.z / blurRegion.w;
var scale = renderScale * (settings.referenceResolution > 0 ? (float)settings.referenceResolution / originalHeight : 1f);
textureDescriptor.height = Mathf.Max(1, Mathf.RoundToInt(scale * blurRegion.w));
textureDescriptor.width = Mathf.Max(1, Mathf.RoundToInt(textureDescriptor.height * aspect));
var referenceHeightForDownScale = textureDescriptor.height;
FindExistingHandleOrAddNew();
bool temp2NeedsInit = true;
if (alpha <= 0)
return;
int totalIterations = 0;
foreach (var section in settings.downscaleSections)
{
var iterations = section.iterations;
var (isSeparable, _, _, _, _) = section.GetSectionBehaviour();
for (int i = 0; i < iterations; i++, totalIterations++)
{
textureDescriptor.height = Mathf.Max(1, Mathf.RoundToInt(referenceHeightForDownScale / Mathf.Pow(1 + alpha, totalIterations + 1)));
textureDescriptor.width = Mathf.Max(1, Mathf.RoundToInt(textureDescriptor.height * aspect));
FindExistingHandleOrAddNew();
if (!isSeparable)
{
temp2NeedsInit = true;
continue;
}
temp2NeedsInit = false;
FindExistingHandleOrAddNew();
}
}
if (temp2NeedsInit)
FindExistingHandleOrAddNew();
void FindExistingHandleOrAddNew()
{
const string textureName = "blurTexture";
while (true)
{
if (currentTextureIdx >= handles.Count)
{
var newHandle = UniversalRenderer.CreateRenderGraphTexture(renderGraph, textureDescriptor, textureName, false, FilterMode.Bilinear);
dimensions.Add((textureDescriptor.width, textureDescriptor.height));
handles.Add(newHandle);
builder.UseTexture(newHandle, AccessFlags.ReadWrite);
indices.Enqueue(currentTextureIdx++);
return;
}
var existingDimensions = dimensions[currentTextureIdx];
if (existingDimensions.width == textureDescriptor.width && existingDimensions.height == textureDescriptor.height)
{
indices.Enqueue(currentTextureIdx++);
return;
}
currentTextureIdx++;
}
}
}
}
private static void Pass(BlurPassData data, UnsafeGraphContext context)
{
var cmd = CommandBufferHelpers.GetNativeCommandBuffer(context.cmd);
var (textureHandle, textureDimensions, textureIndices, camera, featureIdx, renderScale, originalWidth, originalHeight, singlePassVR, multiPassVR, rightEye, haveUIBlurAreas, haveBlurredImageAreas, blurAreas, blurredImageAreas, batchedBlurs, blurredImageLayersSeeLower, blurredImageSeeUIBlurs, uiBlurLayersSeeLower, useComputeShaders, overlayCompatibilityFix) =
(data.textureHandles, data.textureDimensions, data.textureIndices, data.camera, data.featureIdx, data.renderScale, data.originalWidth, data.originalHeight, data.singlePassVR, data.multiPassVR, data.rightEye, data.haveUIBlurAreas, data.haveBlurredImageAreas, data.blurAreas, data.blurredImageAreas,data.batchedBlurs, data.blurredImageLayersSeeLower, data.blurredImageSeeUIBlurs, data.uiBlurLayersSeeLower, data.useComputeShaders, data.overlayCompatibilityFix);
var destinationRequiresClear = haveUIBlurAreas && (!haveBlurredImageAreas || blurredImageSeeUIBlurs);
var key = (camera, featureIdx);
if (blurredImageSeeUIBlurs)
{
HandleUIBlurs();
HandleBlurredImages();
}
else
{
HandleBlurredImages();
HandleUIBlurs(haveBlurredImageAreas);
}
void HandleUIBlurs(bool useTempRT = false)
{
if (!haveUIBlurAreas)
return;
TextureHandle layerHandle;
if (useTempRT)
{
destinationRequiresClear = !blurredImageSeeUIBlurs;
layerHandle = data.temporaryUIBlurFullScreenHandle;
}
else
{
layerHandle = data.instanceHandles[0];
}
if (uiBlurLayersSeeLower)
{
int currentLayer = blurAreas[0].Layer;
foreach (var blur in blurAreas)
{
if (blur.Layer > currentLayer)
{
currentLayer = blur.Layer;
FullScreenBlit(cmd, layerHandle, data.source, fullScreenBlitsMat, 1);
}
ApplyBlurRenderGraph(blur, data.source, layerHandle);
}
}
else
{
foreach (var x in blurAreas)
ApplyBlurRenderGraph(x, data.source, layerHandle);
}
if (!destinationRequiresClear)
FullScreenBlit(cmd, layerHandle, data.source, fullScreenBlitsMat, 1);
}
void HandleBlurredImages()
{
if (!haveBlurredImageAreas)
return;
var numImageLayers = FlexibleBlurFeature.ImageBasedLayersPerCameraDict[key];
var source = data.source;
var destinationIdx = 0;
var destination = data.instanceHandles[destinationIdx];
if (blurredImageLayersSeeLower && destinationIdx < numImageLayers - 1)
{
cmd.SetRenderTarget(destination);
cmd.ClearRenderTarget(false, true, Color.clear);
cmd.SetRenderTarget(source);
FullScreenBlit(cmd, source, destination, fullScreenBlitsMat);
}
var currentLayer = blurredImageAreas[0].Layer;
var currentPriority = blurredImageAreas[0].Priority;
foreach (var blurImage in blurredImageAreas)
{
if (blurImage.Layer > currentLayer || blurImage.Priority > currentPriority)
{
TryApplyBatchedBlurs();
if (blurImage.Layer > currentLayer)
{
destination = data.instanceHandles[++destinationIdx];
if (blurredImageLayersSeeLower)
{
source = data.instanceHandles[destinationIdx - 1];
cmd.SetRenderTarget(source);
if (destinationIdx < numImageLayers - 1)
{
FullScreenBlit(cmd, source, destination, fullScreenBlitsMat);
}
}
}
currentLayer = blurImage.Layer;
currentPriority = blurImage.Priority;
}
if (blurImage.CanBatch)
batchedBlurs.Add((blurImage.Settings, blurImage.Alpha), blurImage);
else
ApplyBlurRenderGraph(blurImage, source, destination);
}
TryApplyBatchedBlurs();
if (blurredImageLayersSeeLower)
cmd.SetRenderTarget(data.source);
void TryApplyBatchedBlurs()
{
foreach (var kvp in batchedBlurs)
{
var fillEntireRenderTexture = false;
foreach (var blur in kvp.Value)
{
if (!blur.FillEntireRenderTexture)
continue;
fillEntireRenderTexture = true;
break;
}
if (!fillEntireRenderTexture && kvp.Value.Count == 1)
{
ApplyBlurRenderGraph(kvp.Value[0], source, destination);
continue;
}
float minX, minY, maxX, maxY;
if (fillEntireRenderTexture)
{
(minX, minY, maxX, maxY) = (0, 0, originalWidth, originalHeight);
}
else
{
(minX, minY, maxX, maxY) = (float.PositiveInfinity, float.PositiveInfinity, float.NegativeInfinity, float.NegativeInfinity);
foreach (var batchedBlur in kvp.Value)
{
minX = Math.Min(minX, batchedBlur.MinX(rightEye));
minY = Math.Min(minY, batchedBlur.MinY(rightEye));
maxX = Math.Max(maxX, batchedBlur.MaxX(rightEye));
maxY = Math.Max(maxY, batchedBlur.MaxY(rightEye));
}
}
if (destinationRequiresClear)
{
cmd.SetRenderTarget(destination);
cmd.ClearRenderTarget(false, true, Color.clear);
cmd.SetRenderTarget(source);
destinationRequiresClear = false;
}
var settings = kvp.Key.blurSettings;
if (singlePassVR)
{
// Left eye extents already calculated. Min/Max that with the right eye values to get a region that covers both eyes.
foreach (var batchedBlur in kvp.Value)
{
minX = Math.Min(minX, batchedBlur.MinX(true));
minY = Math.Min(minY, batchedBlur.MinY(true));
maxX = Math.Max(maxX, batchedBlur.MaxX(true));
maxY = Math.Max(maxY, batchedBlur.MaxY(true));
}
}
var blurRegion = UIBlurCommon.ComputeBlurRegion(minX, minY, maxX, maxY);
ApplyBlurUnifiedRenderGraph(source, destination, settings, blurRegion, singlePassVR ? blurRegion : null, null, null, kvp.Key.alpha, false, Matrix4x4.identity);
}
batchedBlurs.Clear();
}
}
void ApplyBlurRenderGraph(IBlur iBlur, RenderTargetIdentifier source, RenderTargetIdentifier destination)
{
if (!iBlur.HasVisiblePixels(rightEye))
return;
if (destinationRequiresClear)
{
cmd.SetRenderTarget(new RenderTargetIdentifier(destination, 0, CubemapFace.Unknown, -1));
cmd.ClearRenderTarget(false, true, Color.clear);
cmd.SetRenderTarget(source);
destinationRequiresClear = false;
}
if (singlePassVR)
{
var (regionRight, cornersRight, region, corners) = (iBlur.Common.BlurRegionRight, iBlur.Common.ScreenCornersRight, iBlur.Common.BlurRegion, iBlur.Common.ScreenCorners);
ApplyBlurUnifiedRenderGraph(source, destination, iBlur.Settings, region, regionRight, corners, cornersRight, iBlur.Alpha, iBlur.IsAngled, iBlur.Matrix, iBlur.Common.WorldCamera);
}
else
{
var (region, corners) = rightEye ? (iBlur.Common.BlurRegionRight, iBlur.Common.ScreenCornersRight) : (iBlur.Common.BlurRegion, iBlur.Common.ScreenCorners);
ApplyBlurUnifiedRenderGraph(source, destination, iBlur.Settings, region, null, corners, null, iBlur.Alpha, iBlur.IsAngled, iBlur.Matrix, iBlur.Common.WorldCamera);
}
}
void ApplyBlurUnifiedRenderGraph(RenderTargetIdentifier source, RenderTargetIdentifier destination, BlurSettings settings, Vector4 blurRegion, Vector4? blurRegionRight, Vector4[] blurCorners, Vector4[] blurCornersRight, float alpha, bool isAngled, Matrix4x4 transformationMatrix, Camera uiCamera = null)
{
blurRegion *= renderScale;
var hasRightEye = blurRegionRight.HasValue;
if (hasRightEye)
{
blurRegionRight *= renderScale;
var scaleFactorRight = new Vector2(originalWidth / blurRegionRight.Value.z, originalHeight / blurRegionRight.Value.w);
cmd.SetGlobalVector(ScaleFactorRightID, scaleFactorRight);
var offsetRight = scaleFactorRight * new Vector2(blurRegionRight.Value.x / originalWidth, blurRegionRight.Value.y / originalHeight);
cmd.SetGlobalVector(SourceOffsetRightID, offsetRight);
}
var handleIdx = textureIndices.Dequeue();
var temp1 = textureHandle[handleIdx];
var temp2 = temp1;
var temp1Dimensions = textureDimensions[handleIdx];
var temp2Dimensions = temp1Dimensions;
var scaleFactor = new Vector2(originalWidth / blurRegion.z, originalHeight / blurRegion.w);
var offset = scaleFactor * new Vector2(blurRegion.x / originalWidth, blurRegion.y / originalHeight);
cmd.SetGlobalVector(ScaleFactorID, scaleFactor);
cmd.SetGlobalVector(SourceOffsetID, offset);
FullScreenBlit(cmd, source, temp1, regionalBlitsMat, Convert.ToInt32(settings.hqResample));
if (alpha > 0)
{
if (useComputeShaders)
ComputeBlur();
else
TraditionalBlur();
}
FinalBlitToDestination();
void ComputeBlur()
{
int totalIterations = 0;
var threadGroupsX = (temp1Dimensions.width + ThreadGroupSizeX - 1) / ThreadGroupSizeX;
var threadGroupsY = (temp1Dimensions.height + ThreadGroupSizeY - 1) / ThreadGroupSizeY;
var computeShader = hasRightEye ? vrComputeBlurs : computeBlurs;
bool temp2NeedsInit = true;
if (alpha > 0)
{
cmd.SetComputeIntParam(computeShader, ComputeOffsetCenterID, 0);
foreach (var section in settings.downscaleSections)
{
var (isSeparable, setSamplesPerSide, skip, firstKernelIdx, secondKernelIdx) = section.GetSectionBehaviour();
if (skip)
continue;
if (setSamplesPerSide)
{
cmd.SetComputeIntParam(computeShader, TapsPerSideHorComputeID, section.horizontalSamplesPerSide);
cmd.SetComputeIntParam(computeShader, TapsPerSideVertComputeID, section.verticalSamplesPerSide);
}
var iterations = section.iterations;
var baseSampleDistance = section.sampleDistance;
var sampleOffset = 1f;
for (int i = 0; i < iterations; i++, totalIterations++)
{
cmd.SetComputeIntParam(computeShader, ComputeBlurIterationID, i);
sampleOffset *= 0.5f;
var evenIter = i % 2 == 0;
var lastPass = i == iterations - 1;
cmd.SetComputeFloatParam(computeShader, ComputeSampleOffsetID, !evenIter ? -sampleOffset : lastPass ? 0 : sampleOffset);
handleIdx = textureIndices.Dequeue();
temp2 = textureHandle[handleIdx];
temp2Dimensions = textureDimensions[handleIdx];
cmd.SetComputeVectorParam(computeShader, ComputeResultDimensionsID, new Vector2(temp2Dimensions.width, temp2Dimensions.height));
cmd.SetComputeFloatParam(computeShader, ComputeSampleDistID, baseSampleDistance * renderScale);
cmd.SetComputeTextureParam(computeShader, firstKernelIdx, ComputeSourceID, temp1);
cmd.SetComputeTextureParam(computeShader, firstKernelIdx, ComputeResultID, temp2);
threadGroupsX = (temp1Dimensions.width + ThreadGroupSizeX - 1) / ThreadGroupSizeX;
threadGroupsY = (temp1Dimensions.height + ThreadGroupSizeY - 1) / ThreadGroupSizeY;
cmd.DispatchCompute(computeShader, firstKernelIdx, threadGroupsX, threadGroupsY, 1);
if (!isSeparable)
{
temp2NeedsInit = true;
(temp1, temp1Dimensions, temp2, temp2Dimensions) = (temp2, temp2Dimensions, temp1, temp1Dimensions);
continue;
}
temp2NeedsInit = false;
handleIdx = textureIndices.Dequeue();
temp1 = textureHandle[handleIdx];
temp1Dimensions = textureDimensions[handleIdx];
cmd.SetComputeTextureParam(computeShader, secondKernelIdx, ComputeSourceID, temp2);
cmd.SetComputeTextureParam(computeShader, secondKernelIdx, ComputeResultID, temp1);
cmd.DispatchCompute(computeShader, secondKernelIdx, threadGroupsX, threadGroupsY, 1);
}
}
}
if (temp2NeedsInit)
{
handleIdx = textureIndices.Dequeue();
temp2 = textureHandle[handleIdx];
temp2Dimensions = textureDimensions[handleIdx];
cmd.SetComputeVectorParam(computeShader, ComputeResultDimensionsID, new Vector2(temp2Dimensions.width, temp2Dimensions.height));
}
totalIterations = 0;
cmd.SetComputeIntParam(computeShader, ComputeOffsetCenterID, 1);
foreach (var section in settings.blurSections)
{
var (isSeparable, setSamplesPerSide, skip, firstKernelIdx, secondKernelIdx) = section.GetSectionBehaviour();
if (skip)
continue;
if (setSamplesPerSide)
{
cmd.SetComputeIntParam(computeShader, TapsPerSideHorComputeID, section.horizontalSamplesPerSide);
cmd.SetComputeIntParam(computeShader, TapsPerSideVertComputeID, section.verticalSamplesPerSide);
}
var iterations = section.iterations;
var baseSampleDistance = section.sampleDistance;
if (!isSeparable)
{
for (int i = 0; i < iterations; i++, totalIterations++)
{
var evenIter = i % 2 == 0;
if (i == iterations - 1 && evenIter)
cmd.SetComputeFloatParam(computeShader, ComputeSampleOffsetID, 0);
else
cmd.SetComputeFloatParam(computeShader, ComputeSampleOffsetID, evenIter ? 0.5f : -0.5f);
cmd.SetComputeIntParam(computeShader, ComputeBlurIterationID, i);
var sampleDistance = alpha * (baseSampleDistance + settings.blurAdditionalDistancePerIteration * totalIterations);
cmd.SetComputeFloatParam(computeShader, ComputeSampleDistID, sampleDistance * renderScale);
cmd.SetComputeTextureParam(computeShader, firstKernelIdx, ComputeSourceID, temp1);
cmd.SetComputeTextureParam(computeShader, firstKernelIdx, ComputeResultID, temp2);
cmd.DispatchCompute(computeShader, firstKernelIdx, threadGroupsX, threadGroupsY, 1);
(temp1, temp1Dimensions, temp2, temp2Dimensions) = (temp2, temp2Dimensions, temp1, temp1Dimensions);
}
}
else
{
cmd.SetComputeTextureParam(computeShader, firstKernelIdx, ComputeSourceID, temp1);
cmd.SetComputeTextureParam(computeShader, firstKernelIdx, ComputeResultID, temp2);
cmd.SetComputeTextureParam(computeShader, secondKernelIdx, ComputeSourceID, temp2);
cmd.SetComputeTextureParam(computeShader, secondKernelIdx, ComputeResultID, temp1);
for (int i = 0; i < iterations; i++, totalIterations++)
{
var evenIter = i % 2 == 0;
if (i == iterations - 1 && evenIter)
cmd.SetComputeFloatParam(computeShader, ComputeSampleOffsetID, 0);
else
cmd.SetComputeFloatParam(computeShader, ComputeSampleOffsetID, evenIter ? 0.5f : -0.5f);
var sampleDistance = alpha * (baseSampleDistance + settings.blurAdditionalDistancePerIteration * totalIterations);
cmd.SetComputeFloatParam(computeShader, ComputeSampleDistID, sampleDistance * renderScale);
cmd.DispatchCompute(computeShader, firstKernelIdx, threadGroupsX, threadGroupsY, 1);
cmd.DispatchCompute(computeShader, secondKernelIdx, threadGroupsX, threadGroupsY, 1);
}
}
}
}
void TraditionalBlur()
{
int totalIterations = 0;
bool temp2NeedsInit = true;
if (alpha > 0)
{
cmd.SetGlobalInt(OffsetCenterID, 0);
foreach (var section in settings.downscaleSections)
{
var (isSeparable, setSamplesPerSide, _, firstKernelIdx, secondKernelIdx) = section.GetSectionBehaviour();
if (setSamplesPerSide)
{
cmd.SetGlobalInt(TapsPerSideHorID, section.horizontalSamplesPerSide);
cmd.SetGlobalInt(TapsPerSideVertID, section.verticalSamplesPerSide);
}
var iterations = section.iterations;
var baseSampleDistance = section.sampleDistance;
var sampleOffset = 1f;
for (int i = 0; i < iterations; i++, totalIterations++)
{
cmd.SetGlobalInt(BlurIterationID, i);
sampleOffset *= 0.5f;
var evenIter = i % 2 == 0;
if (i == iterations - 1 && evenIter)
cmd.SetGlobalFloat(SampleOffsetID, 0);
else
cmd.SetGlobalFloat(SampleOffsetID, evenIter ? sampleOffset : -sampleOffset);
handleIdx = textureIndices.Dequeue();
temp2 = textureHandle[handleIdx];
temp2Dimensions = textureDimensions[handleIdx];
cmd.SetGlobalFloat(BlurSampleDistID, baseSampleDistance * renderScale);
FullScreenBlit(cmd, temp1, temp2, blursMat, firstKernelIdx);
if (!isSeparable)
{
temp2NeedsInit = true;
(temp1, temp1Dimensions, temp2, temp2Dimensions) = (temp2, temp2Dimensions, temp1, temp1Dimensions);
continue;
}
temp2NeedsInit = false;
handleIdx = textureIndices.Dequeue();
temp1 = textureHandle[handleIdx];
temp1Dimensions = textureDimensions[handleIdx];
FullScreenBlit(cmd, temp2, temp1, blursMat, secondKernelIdx);
}
}
}
if (temp2NeedsInit)
temp2 = textureHandle[textureIndices.Dequeue()];
totalIterations = 0;
cmd.SetGlobalInt(OffsetCenterID, 1);
foreach (var section in settings.blurSections)
{
var (isSeparable, setSamplesPerSide, skip, firstKernelIdx, secondKernelIdx) = section.GetSectionBehaviour();
if (skip)
continue;
if (setSamplesPerSide)
{
cmd.SetGlobalInt(TapsPerSideHorID, section.horizontalSamplesPerSide);
cmd.SetGlobalInt(TapsPerSideVertID, section.verticalSamplesPerSide);
}
var baseSampleDistance = section.sampleDistance;
var iterations = section.iterations;
for (int i = 0; i < iterations; i++, totalIterations++)
{
cmd.SetGlobalInt(BlurIterationID, i);
var evenIter = i % 2 == 0;
if (i == iterations - 1 && evenIter)
cmd.SetGlobalFloat(SampleOffsetID, 0);
else
cmd.SetGlobalFloat(SampleOffsetID, evenIter ? 0.5f : -0.5f);
var sampleDistance = alpha * (baseSampleDistance + settings.blurAdditionalDistancePerIteration * totalIterations);
cmd.SetGlobalFloat(BlurSampleDistID, sampleDistance * renderScale);
FullScreenBlit(cmd, temp1, temp2, blursMat, firstKernelIdx);
if (!isSeparable)
{
(temp1, temp2) = (temp2, temp1);
continue;
}
FullScreenBlit(cmd, temp2, temp1, blursMat, secondKernelIdx);
}
}
}
void FinalBlitToDestination()
{
cmd.SetGlobalFloat(DitherStrengthID, alpha * settings.ditherStrength);
cmd.SetGlobalVector(DestinationRegionSizeID, blurRegion);
if (hasRightEye)
cmd.SetGlobalVector(DestinationRegionSizeRightID, blurRegionRight.Value);
cmd.SetGlobalFloat(VibrancyID, (alpha * settings.vibrancy + 1) * 0.5f);
cmd.SetGlobalFloat(BrightnessID, alpha * settings.brightness);
cmd.SetGlobalFloat(ContrastID, alpha * settings.contrast + 1);
cmd.SetGlobalVector(TintID, alpha * settings.tint);
var useQuadBlit = transformationMatrix != Matrix4x4.identity && (!overlayCompatibilityFix || uiCamera != null);
if (useQuadBlit)
{
if (multiPassVR)
{
BlitToQuad(cmd, temp1, destination, quadBlitsMat, transformationMatrix, blurRegion, blurRegionRight, originalWidth, originalHeight, 0);
}
else
{
cmd.SetProjectionMatrix(uiCamera?.projectionMatrix ?? OverlayUIProjectionMatrix);
cmd.SetViewMatrix(uiCamera?.worldToCameraMatrix ?? Matrix4x4.identity);
BlitToQuad(cmd, temp1, destination, quadBlitsMat, transformationMatrix, blurRegion, blurRegionRight, originalWidth, originalHeight, 0);
cmd.SetProjectionMatrix(camera.projectionMatrix);
cmd.SetViewMatrix(camera.worldToCameraMatrix);
}
}
else
{
if (isAngled)
{
cmd.SetGlobalFloat(RenderScaleID, renderScale);
cmd.SetGlobalVectorArray(CornersID, blurCorners);
if (hasRightEye)
cmd.SetGlobalVectorArray(CornersRightID, blurCornersRight);
}
BlitToRegion(cmd, temp1, destination, regionalBlitsMat, blurRegion, originalWidth, originalHeight, isAngled ? 3 : 2);
}
cmd.SetRenderTarget(data.source);
}
}
}
}
}
#endif