84 lines
2.9 KiB
HLSL
84 lines
2.9 KiB
HLSL
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "/Engine/Private/Common.ush"
|
|
|
|
Texture2D SrcTexture;
|
|
int2 SrcTextureSize;
|
|
|
|
RWTexture2D<float4> DstTexture;
|
|
int2 DstTextureCoord;
|
|
|
|
// Packing swizzles so that RGBA texture (required format for UAV) can be read after mapping on CPU as BGRA
|
|
float4 PackMinMax(in float2 UnPacked)
|
|
{
|
|
uint2 UnPackedUint = floor(UnPacked * 65535.f);
|
|
float4 Packed = float4(
|
|
(float)(UnPackedUint.y >> 8) / 255.f,
|
|
(float)(UnPackedUint.x & 0xff) / 255.f,
|
|
(float)(UnPackedUint.x >> 8) / 255.f,
|
|
(float)(UnPackedUint.y & 0xff) / 255.f);
|
|
return Packed;
|
|
}
|
|
|
|
float2 UnPackMinMax(in float4 Packed)
|
|
{
|
|
uint4 PackedScaled = (uint4)floor(Packed *= 255.f);
|
|
uint2 UnPackedScaled = uint2(PackedScaled.z << 8 | PackedScaled.y, PackedScaled.x << 8 | PackedScaled.w);
|
|
float2 UnPacked = (float2)UnPackedScaled / 65535.f;
|
|
return UnPacked;
|
|
}
|
|
|
|
// Min downsample excludes zero values to avoid empty pixels affecting the calculation
|
|
float Min4(in float4 Values, in float ReplaceZero)
|
|
{
|
|
Values = select(Values == 0, ReplaceZero, Values);
|
|
return min(min(min(Values.x, Values.y), Values.z), Values.w);
|
|
}
|
|
|
|
float Max4(in float4 Values)
|
|
{
|
|
return max(max(max(Values.x, Values.y), Values.z), Values.w);
|
|
}
|
|
|
|
[numthreads(8, 8, 1)]
|
|
void MinMaxHeightCS(uint3 DispatchThreadId : SV_DispatchThreadID)
|
|
{
|
|
if (any(DispatchThreadId.xy * 2 >= (uint2)SrcTextureSize.xy))
|
|
return;
|
|
|
|
#if INPUT_FORMAT_R16
|
|
float T00 = SrcTexture[2 * DispatchThreadId.xy].x;
|
|
float T01 = SrcTexture[2 * DispatchThreadId.xy + int2(0, 1)].x;
|
|
float T10 = SrcTexture[2 * DispatchThreadId.xy + int2(1, 0)].x;
|
|
float T11 = SrcTexture[2 * DispatchThreadId.xy + int2(1, 1)].x;
|
|
float ValueMax = Max4(float4(T00, T01, T10, T11));
|
|
float ValueMin = Min4(float4(T00, T01, T10, T11), ValueMax);
|
|
#elif INPUT_FORMAT_RG16
|
|
float2 T00 = SrcTexture[2 * DispatchThreadId.xy].xy;
|
|
float2 T01 = SrcTexture[2 * DispatchThreadId.xy + int2(0, 1)].xy;
|
|
float2 T10 = SrcTexture[2 * DispatchThreadId.xy + int2(1, 0)].xy;
|
|
float2 T11 = SrcTexture[2 * DispatchThreadId.xy + int2(1, 1)].xy;
|
|
float ValueMax = Max4(float4(T00.y, T01.y, T10.y, T11.y));
|
|
float ValueMin = Min4(float4(T00.x, T01.x, T10.x, T11.x), ValueMax);
|
|
#elif INPUT_FORMAT_RGBA8
|
|
float2 T00 = UnPackMinMax(SrcTexture[2 * DispatchThreadId.xy]);
|
|
float2 T01 = UnPackMinMax(SrcTexture[2 * DispatchThreadId.xy + int2(0, 1)]);
|
|
float2 T10 = UnPackMinMax(SrcTexture[2 * DispatchThreadId.xy + int2(1, 0)]);
|
|
float2 T11 = UnPackMinMax(SrcTexture[2 * DispatchThreadId.xy + int2(1, 1)]);
|
|
float ValueMax = Max4(float4(T00.y, T01.y, T10.y, T11.y));
|
|
float ValueMin = Min4(float4(T00.x, T01.x, T10.x, T11.x), ValueMax);
|
|
#endif
|
|
|
|
#if OUTPUT_FORMAT_RG16
|
|
float4 Output = float4(ValueMin, ValueMax, 0, 0);
|
|
#elif OUTPUT_FORMAT_RGBA8
|
|
float4 Output = PackMinMax(float2(ValueMin, ValueMax));
|
|
#endif
|
|
|
|
#if OUTPUT_TYPE_TEXEL
|
|
DstTexture[DstTextureCoord] = Output;
|
|
#elif OUTPUT_TYPE_TEXTURE
|
|
DstTexture[DispatchThreadId.xy] = Output;
|
|
#endif
|
|
}
|