Files
UnrealEngine/Engine/Plugins/VirtualProduction/GeometryMask/Shaders/Private/GeometryMaskJFStepCS.usf
2025-05-18 13:04:45 +08:00

103 lines
3.2 KiB
HLSL

// Copyright Epic Games, Inc. All Rights Reserved.
#include "/Engine/Public/Platform.ush"
uint2 InputDimensions;
float2 OneOverInputDimensions;
float2 UVRatioAdjustment;
uint4 StepSize; // per-channel
uint4 ChannelMask; // whether to calculate for this step
Buffer<float4> InputBuffer;
RWBuffer<float4> OutputBuffer;
[numthreads(TILE_SIZE, TILE_SIZE, 1)]
void MainCS(
uint3 DispatchThreadId : SV_DispatchThreadID,
uint3 GroupThreadId : SV_GroupThreadID,
uint3 GroupId : SV_GroupID)
{
uint2 PixelCoord = DispatchThreadId.xy;
if (PixelCoord.x > InputDimensions.x - 1 || PixelCoord.y > InputDimensions.y - 1)
{
return;
}
const uint RowLength = InputDimensions.x * NUM_CHANNELS;
uint PixelCoord1D = (PixelCoord.y * RowLength) + (PixelCoord.x * NUM_CHANNELS);
static uint2 NeighborOffsetIndices[] =
{
{-1, 1}, {0, 1}, {1, 1},
{-1, 0}, {0, 0}, {1, 0},
{-1, -1}, {0, -1}, {1, -1}
};
#if NUM_CHANNELS == 1
float MinDistance[NUM_CHANNELS] = { 100000000 };
float4 MinSample[NUM_CHANNELS] = { float4(0,0,0,0) };
#elif NUM_CHANNELS == 2
float MinDistance[NUM_CHANNELS] = { 100000000, 100000000 };
float4 MinSample[NUM_CHANNELS] = { float4(0,0,0,0), float4(0,0,0,0) };
#elif NUM_CHANNELS == 3
float MinDistance[NUM_CHANNELS] = { 100000000, 100000000, 100000000 };
float4 MinSample[NUM_CHANNELS] = { float4(0,0,0,0), float4(0,0,0,0), float4(0,0,0,0) };
#elif NUM_CHANNELS == 4
float MinDistance[NUM_CHANNELS] = { 100000000, 100000000, 100000000, 100000000 };
float4 MinSample[NUM_CHANNELS] = { float4(0,0,0,0), float4(0,0,0,0), float4(0,0,0,0), float4(0,0,0,0) };
#endif
float X = (float)PixelCoord.x + 0.5;
float Y = (float)PixelCoord.y + 0.5;
const float2 UV = float2(X, Y) * OneOverInputDimensions * UVRatioAdjustment;
// Perform on each of R,G,B,A
[unroll]
for (int ChannelIdx = 0; ChannelIdx < NUM_CHANNELS; ++ChannelIdx)
{
float4 Input = InputBuffer[PixelCoord1D + ChannelIdx];
const uint2 StepSizeWithChannel = StepSize[ChannelIdx] * uint2(1, 1);
// Check if we should calculate this channel (for this step)
if (ChannelMask[ChannelIdx] == 0)
{
MinSample[ChannelIdx] = Input[ChannelIdx];
continue;
}
MinDistance[ChannelIdx] = 1000000000;
MinSample[ChannelIdx] = float4(0,0,0,0);
[unroll]
for (int HorizontalIdx = 0; HorizontalIdx < 3; ++HorizontalIdx)
{
[unroll]
for (int VerticalIdx = 0; VerticalIdx < 3; ++VerticalIdx)
{
uint NeighborIdx = (VerticalIdx * KERNEL_SIZE) + HorizontalIdx;
uint2 NeighborPixelCoord = PixelCoord + (NeighborOffsetIndices[NeighborIdx] * StepSizeWithChannel);
// Prevents border banding
NeighborPixelCoord = min(InputDimensions - 1, max(uint2(1,1), NeighborPixelCoord));
uint NeighborPixelCoord1D = (NeighborPixelCoord.y * RowLength) + (NeighborPixelCoord.x * NUM_CHANNELS);
float4 NeighborSample = InputBuffer[NeighborPixelCoord1D + ChannelIdx];
if (NeighborSample.x + NeighborSample.y == 0.0)
{
continue;
}
const float Distance = length(NeighborSample.xy - UV);
if (Distance < MinDistance[ChannelIdx])
{
MinDistance[ChannelIdx] = Distance;
MinSample[ChannelIdx] = NeighborSample;
}
}
}
MinSample[ChannelIdx].a = Input.a;
OutputBuffer[PixelCoord1D + ChannelIdx] = MinSample[ChannelIdx];
}
}