Files
Cielonos/Assets/Plugins/FlexibleUI/FlexibleBlur/Resources/ComputeBlurs.compute
SoulliesOfficial 649b7a5ddc 更新
2026-05-23 08:27:50 -04:00

282 lines
13 KiB
Plaintext

#define THREADGROUP_DIMENSION_X 8
#define THREADGROUP_DIMENSION_Y 8
#pragma kernel ThreeTapCheckerboard
#pragma kernel FourTapCorners
#pragma kernel FourTapCross
#pragma kernel FiveTapStar
#pragma kernel SevenTapHexagonal
#pragma kernel EightTapCornersAndCross
#pragma kernel NineTapOctagonal
#pragma kernel QuadraticHorizontal
#pragma kernel QuadraticVertical
#pragma kernel GaussianHorizontal
#pragma kernel GaussianVertical
Texture2D<half4> Source;
RWTexture2D<half4> Result;
float2 ResultDimensions;
float SampleDist;
float SampleOffset;
bool OffsetCenter;
uint BlurIteration;
uint TapsPerSideHor;
uint TapsPerSideVert;
SamplerState linearClampSampler;
[numthreads(THREADGROUP_DIMENSION_X, THREADGROUP_DIMENSION_Y, 1)]
void ThreeTapCheckerboard(uint3 id : SV_DispatchThreadID)
{
const float2 idf = id.xy + 0.5h;
const half2 uv = idf / ResultDimensions;
const float2 texelIndex = floor(idf);
const half checker = 1 - 2 * fmod(floor(0.5h * BlurIteration) + texelIndex.x + texelIndex.y, 2);
const half orientation = fmod(BlurIteration, 2);
const half invOrientation = 1.0h - orientation;
const half texelWidth = 1.0h / ResultDimensions.x;
const half texelHeight = 1.0h / ResultDimensions.y;
const half horOffset = texelWidth * SampleDist;
const half vertOffset = texelHeight * SampleDist;
const half2 offset1 = half2(
checker * (0.5h * texelWidth * invOrientation + horOffset * orientation),
checker * (vertOffset * invOrientation + 0.5h * texelHeight * orientation)
);
const half2 offset2 = half2(
lerp(horOffset, -horOffset * checker, orientation),
lerp(-vertOffset * checker, vertOffset, orientation)
);
const half2 offset3 = half2(
lerp(-horOffset, -horOffset * checker, orientation),
lerp(-vertOffset * checker, -vertOffset, orientation)
);
const half4 sum = 0.334h * Source.SampleLevel(linearClampSampler, uv + offset1, 0)
+ 0.333h * Source.SampleLevel(linearClampSampler, uv + offset2, 0)
+ 0.333h * Source.SampleLevel(linearClampSampler, uv + offset3, 0);
Result[id.xy] = sum;
}
[numthreads(THREADGROUP_DIMENSION_X, THREADGROUP_DIMENSION_Y, 1)]
void FourTapCorners(uint3 id : SV_DispatchThreadID)
{
const float2 idf = id.xy + 0.5h;
const half2 uv = idf / ResultDimensions;
const half2 sampleDist = SampleDist / ResultDimensions;
const half4 sum = 0.25h * Source.SampleLevel(linearClampSampler, uv + half2( sampleDist.x, sampleDist.y), 0)
+ 0.25h * Source.SampleLevel(linearClampSampler, uv + half2(-sampleDist.x, sampleDist.y), 0)
+ 0.25h * Source.SampleLevel(linearClampSampler, uv + half2( sampleDist.x, -sampleDist.y), 0)
+ 0.25h * Source.SampleLevel(linearClampSampler, uv + half2(-sampleDist.x, -sampleDist.y), 0);
Result[id.xy] = sum;
}
[numthreads(THREADGROUP_DIMENSION_X, THREADGROUP_DIMENSION_Y, 1)]
void FourTapCross(uint3 id : SV_DispatchThreadID)
{
const float2 idf = id.xy + 0.5h;
const half2 uv = idf / ResultDimensions;
const half2 sampleDist = SampleDist / ResultDimensions;
const half2 texelSize = half2(1.h / ResultDimensions.x, 1.h / ResultDimensions.y);
const half2 halfTexelOffset = texelSize * SampleOffset;
const half4 sum = 0.25h * Source.SampleLevel(linearClampSampler, uv + half2( sampleDist.x, halfTexelOffset.y), 0)
+ 0.25h * Source.SampleLevel(linearClampSampler, uv + half2(-sampleDist.x, halfTexelOffset.y), 0)
+ 0.25h * Source.SampleLevel(linearClampSampler, uv + half2( halfTexelOffset.x, sampleDist.y), 0)
+ 0.25h * Source.SampleLevel(linearClampSampler, uv + half2( halfTexelOffset.x, -sampleDist.y), 0);
Result[id.xy] = sum;
}
[numthreads(THREADGROUP_DIMENSION_X, THREADGROUP_DIMENSION_Y, 1)]
void FiveTapStar(uint3 id : SV_DispatchThreadID)
{
const float2 idf = id.xy + 0.5h;
const half2 uv = idf / ResultDimensions;
const half2 offset = SampleDist / ResultDimensions;
const half2 texelSize = half2(1.h / ResultDimensions.x, 1.h / ResultDimensions.y);
const half2 halfTexelOffset = texelSize * SampleOffset;
const half4 sum = 0.5h * Source.SampleLevel(linearClampSampler, uv + halfTexelOffset * OffsetCenter, 0)
+ 0.125h * Source.SampleLevel(linearClampSampler, uv + half2( offset.x, offset.y), 0)
+ 0.125h * Source.SampleLevel(linearClampSampler, uv + half2(-offset.x, offset.y), 0)
+ 0.125h * Source.SampleLevel(linearClampSampler, uv + half2( offset.x, -offset.y), 0)
+ 0.125h * Source.SampleLevel(linearClampSampler, uv + half2(-offset.x, -offset.y), 0);
Result[id.xy] = sum;
}
[numthreads(THREADGROUP_DIMENSION_X, THREADGROUP_DIMENSION_Y, 1)]
void SevenTapHexagonal(uint3 id : SV_DispatchThreadID)
{
const float2 idf = id.xy + 0.5h;
const half2 uv = idf / ResultDimensions;
const half sampleDistanceX = SampleDist / ResultDimensions.x * 0.57735024648h;
const half sampleDistanceY = SampleDist / ResultDimensions.y;
const half2 texelSize = half2(1.h / ResultDimensions.x, 1.h / ResultDimensions.y);
const half2 halfTexelOffset = texelSize * SampleOffset;
const half4 sum = 0.28h * Source.SampleLevel(linearClampSampler, uv + halfTexelOffset * OffsetCenter, 0)
+ 0.12h * Source.SampleLevel(linearClampSampler, uv + half2( sampleDistanceX * 2, halfTexelOffset.y), 0)
+ 0.12h * Source.SampleLevel(linearClampSampler, uv + half2(-sampleDistanceX * 2, halfTexelOffset.y), 0)
+ 0.12h * Source.SampleLevel(linearClampSampler, uv + half2( sampleDistanceX, sampleDistanceY), 0)
+ 0.12h * Source.SampleLevel(linearClampSampler, uv + half2( sampleDistanceX, -sampleDistanceY), 0)
+ 0.12h * Source.SampleLevel(linearClampSampler, uv + half2(-sampleDistanceX, sampleDistanceY), 0)
+ 0.12h * Source.SampleLevel(linearClampSampler, uv + half2(-sampleDistanceX, -sampleDistanceY), 0);
Result[id.xy] = sum;
}
[numthreads(THREADGROUP_DIMENSION_X, THREADGROUP_DIMENSION_Y, 1)]
void EightTapCornersAndCross(uint3 id : SV_DispatchThreadID)
{
const float2 idf = id.xy + 0.5h;
const half2 uv = idf / ResultDimensions;
const half2 sampleDist = SampleDist / ResultDimensions;
const half2 texelSize = half2(1.h / ResultDimensions.x, 1.h / ResultDimensions.y);
const half2 halfTexelOffset = texelSize * SampleOffset;
const half4 sum = 0.165h * Source.SampleLevel(linearClampSampler, uv + half2( sampleDist.x, sampleDist.y), 0)
+ 0.165h * Source.SampleLevel(linearClampSampler, uv + half2(-sampleDist.x, sampleDist.y), 0)
+ 0.165h * Source.SampleLevel(linearClampSampler, uv + half2( sampleDist.x, -sampleDist.y), 0)
+ 0.165h * Source.SampleLevel(linearClampSampler, uv + half2(-sampleDist.x, -sampleDist.y), 0)
+ 0.085h * Source.SampleLevel(linearClampSampler, uv + half2( halfTexelOffset.x, sampleDist.y * 2), 0)
+ 0.085h * Source.SampleLevel(linearClampSampler, uv + half2( halfTexelOffset.x, -sampleDist.y * 2), 0)
+ 0.085h * Source.SampleLevel(linearClampSampler, uv + half2( sampleDist.x * 2, halfTexelOffset.y), 0)
+ 0.085h * Source.SampleLevel(linearClampSampler, uv + half2(-sampleDist.x * 2, halfTexelOffset.y), 0);
Result[id.xy] = sum;
}
[numthreads(THREADGROUP_DIMENSION_X, THREADGROUP_DIMENSION_Y, 1)]
void NineTapOctagonal(uint3 id : SV_DispatchThreadID)
{
const float2 idf = id.xy + 0.5h;
const half2 uv = idf / ResultDimensions;
const half2 sampleDist = SampleDist / ResultDimensions;
const half2 sampleDist2 = sampleDist * 1.414427h;
const half2 texelSize = half2(1.h / ResultDimensions.x, 1.h / ResultDimensions.y);
const half2 halfTexelOffset = texelSize * SampleOffset;
const half4 sum = 0.2h * Source.SampleLevel(linearClampSampler, uv + halfTexelOffset * OffsetCenter, 0)
+ 0.1h * Source.SampleLevel(linearClampSampler, uv + half2( sampleDist2.x, halfTexelOffset.y), 0)
+ 0.1h * Source.SampleLevel(linearClampSampler, uv + half2(-sampleDist2.x, halfTexelOffset.y), 0)
+ 0.1h * Source.SampleLevel(linearClampSampler, uv + half2( halfTexelOffset.x, sampleDist2.y), 0)
+ 0.1h * Source.SampleLevel(linearClampSampler, uv + half2( halfTexelOffset.x, -sampleDist2.y), 0)
+ 0.1h * Source.SampleLevel(linearClampSampler, uv + half2( sampleDist.x, sampleDist.y), 0)
+ 0.1h * Source.SampleLevel(linearClampSampler, uv + half2(-sampleDist.x, sampleDist.y), 0)
+ 0.1h * Source.SampleLevel(linearClampSampler, uv + half2( sampleDist.x, -sampleDist.y), 0)
+ 0.1h * Source.SampleLevel(linearClampSampler, uv + half2(-sampleDist.x, -sampleDist.y), 0);
Result[id.xy] = sum;
}
[numthreads(THREADGROUP_DIMENSION_X, THREADGROUP_DIMENSION_Y, 1)]
void QuadraticHorizontal(uint3 id : SV_DispatchThreadID)
{
float2 idf = id.xy + 0.5h;
const half2 uv = idf / ResultDimensions;
const half sampleDistanceX = SampleDist / ResultDimensions.x;
const half2 texelSize = half2(1.h / ResultDimensions.x, 1.h / ResultDimensions.y);
const half2 halfTexelOffset = texelSize * SampleOffset;
half4 color = Source.SampleLevel(linearClampSampler, uv + halfTexelOffset * OffsetCenter, 0);
half totalWeight = 1.h;
for (uint slot = 1; slot <= TapsPerSideHor; slot++)
{
const half t = 1 - slot / (TapsPerSideHor + 1.);
const half weight = t * t;
color += weight * Source.SampleLevel(linearClampSampler, uv + half2( sampleDistanceX * slot, halfTexelOffset.y), 0);
color += weight * Source.SampleLevel(linearClampSampler, uv + half2(-sampleDistanceX * slot, halfTexelOffset.y), 0);
totalWeight += 2 * weight;
}
Result[id.xy] = color / totalWeight;
}
[numthreads(THREADGROUP_DIMENSION_X, THREADGROUP_DIMENSION_Y, 1)]
void QuadraticVertical(uint3 id : SV_DispatchThreadID)
{
float2 idf = id.xy + 0.5h;
const half2 uv = idf / ResultDimensions;
const half sampleDistanceY = SampleDist / ResultDimensions.y;
const half2 texelSize = half2(1.h / ResultDimensions.x, 1.h / ResultDimensions.y);
const half2 halfTexelOffset = texelSize * SampleOffset;
half4 color = Source.SampleLevel(linearClampSampler, uv + halfTexelOffset * OffsetCenter, 0);
half totalWeight = 1.h;
for (uint slot = 1; slot <= TapsPerSideVert; slot++)
{
const half t = 1 - slot / (TapsPerSideVert + 1.);
const half weight = t * t;
color += weight * Source.SampleLevel(linearClampSampler, uv + half2(halfTexelOffset.x, sampleDistanceY * slot), 0);
color += weight * Source.SampleLevel(linearClampSampler, uv + half2(halfTexelOffset.x, -sampleDistanceY * slot), 0);
totalWeight += 2 * weight;
}
Result[id.xy] = color / totalWeight;
}
[numthreads(THREADGROUP_DIMENSION_X, THREADGROUP_DIMENSION_Y, 1)]
void GaussianHorizontal(uint3 id : SV_DispatchThreadID)
{
float2 idf = id.xy + 0.5h;
const half2 uv = idf / ResultDimensions;
const half lowTapAdjust = 0.8h * max(0, 6 - TapsPerSideHor * 0.2h);
const half sigma = (lowTapAdjust + TapsPerSideHor) * 2 / 6.;
const half weightExpDivisor = -2 * sigma * sigma;
const half sampleDistanceX = SampleDist / ResultDimensions.x;
const half2 texelSize = half2(1.h / ResultDimensions.x, 1.h / ResultDimensions.y);
const half2 halfTexelOffset = texelSize * SampleOffset;
half4 color = Source.SampleLevel(linearClampSampler, uv + halfTexelOffset * OffsetCenter, 0);
half totalWeight = 1.h;
for (uint slot = 1; slot <= TapsPerSideHor; slot++)
{
const half weight = exp(slot * slot / weightExpDivisor);
color += weight * Source.SampleLevel(linearClampSampler, uv + half2( sampleDistanceX * slot, halfTexelOffset.y), 0);
color += weight * Source.SampleLevel(linearClampSampler, uv + half2(-sampleDistanceX * slot, halfTexelOffset.y), 0);
totalWeight += 2 * weight;
}
Result[id.xy] = color / totalWeight;
}
[numthreads(THREADGROUP_DIMENSION_X, THREADGROUP_DIMENSION_Y, 1)]
void GaussianVertical(uint3 id : SV_DispatchThreadID)
{
float2 idf = id.xy + 0.5h;
const half2 uv = idf / ResultDimensions;
const half lowTapAdjust = 0.8h * max(0, 6 - TapsPerSideVert * 0.2h);
const half sigma = (lowTapAdjust + TapsPerSideVert) * 2 / 6.;
const half weightExpDivisor = -2 * sigma * sigma;
const half sampleDistanceY = SampleDist / ResultDimensions.y;
const half2 texelSize = half2(1.h / ResultDimensions.x, 1.h / ResultDimensions.y);
const half2 halfTexelOffset = texelSize * SampleOffset;
half4 color = Source.SampleLevel(linearClampSampler, uv + halfTexelOffset * OffsetCenter, 0);
half totalWeight = 1.h;
for (uint slot = 1; slot <= TapsPerSideVert; slot++)
{
const half weight = exp(slot * slot / weightExpDivisor);
color += weight * Source.SampleLevel(linearClampSampler, uv + half2(halfTexelOffset.x, sampleDistanceY * slot), 0);
color += weight * Source.SampleLevel(linearClampSampler, uv + half2(halfTexelOffset.x, -sampleDistanceY * slot), 0);
totalWeight += 2 * weight;
}
Result[id.xy] = color / totalWeight;
}