169 lines
7.2 KiB
HLSL
169 lines
7.2 KiB
HLSL
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
/*=============================================================================
|
|
PostProcessTestImage.usf: PostProcessing shader to show a test image
|
|
=============================================================================*/
|
|
|
|
#include "Common.ush"
|
|
#include "PostProcessCommon.ush"
|
|
#include "DeferredShadingCommon.ush"
|
|
#include "ScreenPass.ush"
|
|
|
|
SCREEN_PASS_TEXTURE_VIEWPORT(Output)
|
|
|
|
uint FrameNumber;
|
|
float FrameTime;
|
|
|
|
float ComputeDistanceToViewRect(int2 PixelPos, int Border)
|
|
{
|
|
return ComputeDistanceToRect(PixelPos, int2(Output_ViewportMin) + Border, int2(Output_ViewportSize) - Border * 2, false);
|
|
}
|
|
|
|
float Quantize(float x, float Count)
|
|
{
|
|
return ceil(x * Count - 1.0f) / (Count - 1.0f);
|
|
}
|
|
|
|
void MainPS(noperspective float4 UVAndScreenPos : TEXCOORD0, float4 SvPosition : SV_POSITION, out float4 OutColor : SV_Target0)
|
|
{
|
|
OutColor = 0;
|
|
|
|
float2 UV = UVAndScreenPos.xy;
|
|
// full res
|
|
int2 PixelPos = (int2)SvPosition.xy;
|
|
// 1/2 res
|
|
int2 PixelPos2 = PixelPos / 2;
|
|
// 1/32 res
|
|
int2 PixelPos6 = PixelPos / 32;
|
|
//
|
|
int2 ScreenCenter = (int2)(Output_ViewportMin + Output_ViewportSize / 2);
|
|
|
|
// highest frequency dither pattern (2x2)
|
|
float BlackWhiteDither1 = ((uint)PixelPos.x % 2) == ((uint)PixelPos.y % 2);
|
|
// checker board pattern (4x4)
|
|
float BlackWhiteDither2 = ((uint)PixelPos2.x % 2) == ((uint)PixelPos2.y % 2);
|
|
// checker board pattern (4x4)
|
|
float BlackWhiteDither6 = ((uint)PixelPos6.x % 2) == ((uint)PixelPos6.y % 2);
|
|
|
|
// grey panning bars on grey background to see VSync issues
|
|
{
|
|
// no antialiasing to avoid changes when upscaling
|
|
float Mask = saturate(1 - ComputeDistanceToRect(PixelPos, (int2)(Output_ViewportMin + Output_ViewportSize * float2(0.9f, 0.0f)), int2(Output_ViewportSize * float2(0.1f, 1.0f))));
|
|
|
|
// speed - higher value is more useful to see VSync issues
|
|
const uint PixelsPerFrame = 8;
|
|
|
|
bool bLine = ((FrameNumber * PixelsPerFrame) - PixelPos.x) % 64 > 32;
|
|
OutColor = bLine ? float4(0.5f, 0.5f, 0.5f, 0) : float4(0.2f, 0.2f, 0.2f, 0);
|
|
}
|
|
|
|
// 4 white pixel wide lines with a black line between
|
|
float ViewportBorders;
|
|
{
|
|
uint ViewPortRectDistance = (uint)ComputeDistanceToViewRect(PixelPos, 7) + 7;
|
|
|
|
ViewportBorders = (ViewPortRectDistance % 2) == 0;
|
|
}
|
|
OutColor += ViewportBorders;
|
|
|
|
{
|
|
float CenterDist = ComputeDistanceToRect(PixelPos, ScreenCenter, 0);
|
|
|
|
// round safety border
|
|
{
|
|
float CircleSize = min(Output_ViewportSize.x, Output_ViewportSize.y) / 2 * 0.78f / 16;
|
|
|
|
float SafetyRectDist = ComputeDistanceToRect(PixelPos, (int2)(Output_ViewportMin + Output_ViewportSize * 0.1f), (int2)(Output_ViewportSize * 0.8f));
|
|
|
|
float InnerCircleThickness = 1.0f;
|
|
float OuterCircleThickness = 7.0f;
|
|
float ThinCircleMask = saturate(SafetyRectDist - CircleSize) * (1 - saturate(SafetyRectDist - CircleSize - InnerCircleThickness));
|
|
float ThickCircleMask = (1 - saturate(SafetyRectDist - CircleSize - InnerCircleThickness - OuterCircleThickness));
|
|
|
|
OutColor = lerp(OutColor, ThinCircleMask.xxxx * float4(0.5f, 0.5f, 0.5f, 0.5f), ThickCircleMask.xxxx);
|
|
}
|
|
|
|
// medium circle
|
|
{
|
|
float CircleSize = min(Output_ViewportSize.x, Output_ViewportSize.y) / 2 * 0.78f / 2;
|
|
|
|
// we want to see good antialiasing but not too blurry so we can judge artifacts
|
|
float InnerCircleThickness = 1.0f;
|
|
float ThinCircleMask = saturate(CenterDist - CircleSize) * (1 - saturate(CenterDist - CircleSize - InnerCircleThickness));
|
|
float ThickCircleMask = saturate(CenterDist - CircleSize + 3) * (1 - saturate(CenterDist - CircleSize - InnerCircleThickness - 3));
|
|
|
|
OutColor = lerp(OutColor, ThinCircleMask.xxxx, ThickCircleMask.xxxx);
|
|
}
|
|
|
|
// smallest circle
|
|
{
|
|
float CircleSize = min(Output_ViewportSize.x, Output_ViewportSize.y) / 2 * 0.78f / 16;
|
|
|
|
// we want to see good antialiasing but not too blurry so we can judge artifacts
|
|
float InnerCircleThickness = 1.0f;
|
|
float ThinCircleMask = saturate(CenterDist - CircleSize) * (1 - saturate(CenterDist - CircleSize - InnerCircleThickness));
|
|
float ThickCircleMask = saturate(CenterDist - CircleSize + 3) * (1 - saturate(CenterDist - CircleSize - InnerCircleThickness - 3));
|
|
|
|
OutColor = lerp(OutColor, ThinCircleMask.xxxx, ThickCircleMask.xxxx);
|
|
}
|
|
|
|
// Red green blue
|
|
{
|
|
// no antialiasing to avoid changes when upscaling
|
|
int RedMask = ComputeDistanceToRect(PixelPos, (int2)(Output_ViewportMin + Output_ViewportSize * float2(0.1f, 0.45f)), (int2)(Output_ViewportSize * float2(0.04f, 0.1f)));
|
|
int GreenMask = ComputeDistanceToRect(PixelPos, (int2)(Output_ViewportMin + Output_ViewportSize * float2(0.15f, 0.45f)), (int2)(Output_ViewportSize * float2(0.04f, 0.1f)));
|
|
int BlueMask = ComputeDistanceToRect(PixelPos, (int2)(Output_ViewportMin + Output_ViewportSize * float2(0.2f, 0.45f)), (int2)(Output_ViewportSize * float2(0.04f, 0.1f)));
|
|
|
|
OutColor = lerp(OutColor, float4(1, 0, 0, 0), (float)(RedMask < 1));
|
|
OutColor = lerp(OutColor, float4(0, 1, 0, 0), (float)(GreenMask < 1));
|
|
OutColor = lerp(OutColor, float4(0, 0, 1, 0), (float)(BlueMask < 1));
|
|
|
|
if(RedMask == 2 || GreenMask == 2 || BlueMask == 2)
|
|
{
|
|
// white border
|
|
OutColor = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
// top 3 bars
|
|
{
|
|
uint2 LeftTopBars = uint2(Output_ViewportMin + Output_ViewportSize * float2(0.5f, 0.1f));
|
|
int2 SizeBars = (int2)(Output_ViewportSize * float2(0.4f, 0.05f));
|
|
|
|
bool FirstBarMask = ComputeDistanceToRect(PixelPos, (int2)(LeftTopBars + Output_ViewportSize * float2(0.0f, 0.00f)), SizeBars, false) == 0;
|
|
bool SecondBarMask = ComputeDistanceToRect(PixelPos, (int2)(LeftTopBars + Output_ViewportSize * float2(0.0f, 0.06f)), SizeBars, false) == 0;
|
|
bool ThirdBarMask = ComputeDistanceToRect(PixelPos, (int2)(LeftTopBars + Output_ViewportSize * float2(0.0f, 0.12f)), SizeBars, false) == 0;
|
|
|
|
float Fraction = saturate((PixelPos.x - LeftTopBars.x) / (SizeBars.x - 1.0f));
|
|
|
|
// moving bars (ideally little affected by hitches and framerate)
|
|
float BarState = frac(FrameTime - PixelPos.x / 64.0f) < 0.5f;
|
|
OutColor = lerp(OutColor, float4(BarState, BarState, 1.0f, 0), FirstBarMask);
|
|
// finest checkerboard pattern
|
|
OutColor += BlackWhiteDither1 * SecondBarMask;
|
|
// more coarse checkerboard pattern
|
|
OutColor += BlackWhiteDither2 * ThirdBarMask;
|
|
}
|
|
|
|
// bottom 3 bars
|
|
{
|
|
uint2 LeftTopBars = uint2(Output_ViewportMin + Output_ViewportSize * float2(0.1f, 0.85f - 0.12f));
|
|
int2 SizeBars = (int2)(Output_ViewportSize * float2(0.8f, 0.05f));
|
|
|
|
bool FirstBarMask = ComputeDistanceToRect(PixelPos, (int2)(LeftTopBars + Output_ViewportSize * float2(0.0f, 0.00f)), SizeBars, false) == 0;
|
|
bool SecondBarMask = ComputeDistanceToRect(PixelPos, (int2)(LeftTopBars + Output_ViewportSize * float2(0.0f, 0.06f)), SizeBars, false) == 0;
|
|
bool ThirdBarMask = ComputeDistanceToRect(PixelPos, (int2)(LeftTopBars + Output_ViewportSize * float2(0.0f, 0.12f)), SizeBars, false) == 0;
|
|
|
|
float Fraction = saturate((PixelPos.x - LeftTopBars.x) / (SizeBars.x - 1.0f));
|
|
|
|
// bright greyscale blocks (255 - 19 is the white reference)
|
|
OutColor += lerp(255 - 2 * 19, 255, Quantize(Fraction, 8)) / 255.0f * FirstBarMask;
|
|
// dark distinct greyscale blocks (16 is the black reference)
|
|
OutColor += lerp(0, 2 * 16, Quantize(Fraction, 8)) / 255.0f * SecondBarMask;
|
|
// greyscale gradient
|
|
OutColor += Fraction * ThirdBarMask;
|
|
}
|
|
|
|
OutColor.rgb = ColorCorrection(OutColor.rgb);
|
|
} |