216 lines
6.9 KiB
HLSL
216 lines
6.9 KiB
HLSL
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
/*=============================================================================
|
|
PostProcessCommon.usf: PostProcessing shared functions and structures.
|
|
=============================================================================*/
|
|
|
|
#pragma once
|
|
|
|
#include "SceneTexturesCommon.ush"
|
|
|
|
/// e.g.
|
|
// PostprocessInput0.SampleLevel(PostprocessInput0Sampler, float2 UV, 0)
|
|
// Texture2DSample(PostprocessInput0, PostprocessInput0Sampler, float2 UV)
|
|
// PostprocessInput0.Load(Texel.xyz)
|
|
// PostprocessInput0.GetDimensions(uint, out uint width, out uint height, out uint levels)
|
|
// PostprocessInput0.GetDimensions(uint, out float width, out float height, out float levels)
|
|
// PostprocessInput0.GetDimensions(out uint width, out uint height)
|
|
// PostprocessInput0.GetDimensions(out float width, out float height)
|
|
Texture2D PostprocessInput0;
|
|
SamplerState PostprocessInput0Sampler;
|
|
Texture2D PostprocessInput1;
|
|
SamplerState PostprocessInput1Sampler;
|
|
Texture2D PostprocessInput2;
|
|
SamplerState PostprocessInput2Sampler;
|
|
Texture2D PostprocessInput3;
|
|
SamplerState PostprocessInput3Sampler;
|
|
Texture2D PostprocessInput4;
|
|
SamplerState PostprocessInput4Sampler;
|
|
Texture2D PostprocessInput5;
|
|
SamplerState PostprocessInput5Sampler;
|
|
Texture2D PostprocessInput6;
|
|
SamplerState PostprocessInput6Sampler;
|
|
Texture2D PostprocessInput7;
|
|
SamplerState PostprocessInput7Sampler;
|
|
Texture2D PostprocessInput8;
|
|
SamplerState PostprocessInput8Sampler;
|
|
Texture2D PostprocessInput9;
|
|
SamplerState PostprocessInput9Sampler;
|
|
Texture2D PostprocessInput10;
|
|
SamplerState PostprocessInput10Sampler;
|
|
|
|
// width, height, 1/width, 1/height
|
|
float4 PostprocessInput0Size;
|
|
float4 PostprocessInput1Size;
|
|
float4 PostprocessInput2Size;
|
|
float4 PostprocessInput3Size;
|
|
float4 PostprocessInput4Size;
|
|
float4 PostprocessInput5Size;
|
|
float4 PostprocessInput6Size;
|
|
float4 PostprocessInput7Size;
|
|
float4 PostprocessInput8Size;
|
|
float4 PostprocessInput9Size;
|
|
float4 PostprocessInput10Size;
|
|
|
|
// xy = min valid BufferUV for a bilinear sampler in PostprocessInput%d, zw = max valid BufferUV for a bilinear sampler.
|
|
float4 PostprocessInput0MinMax;
|
|
float4 PostprocessInput1MinMax;
|
|
float4 PostprocessInput2MinMax;
|
|
float4 PostprocessInput3MinMax;
|
|
float4 PostprocessInput4MinMax;
|
|
float4 PostprocessInput5MinMax;
|
|
float4 PostprocessInput6MinMax;
|
|
float4 PostprocessInput7MinMax;
|
|
float4 PostprocessInput8MinMax;
|
|
float4 PostprocessInput9MinMax;
|
|
float4 PostprocessInput10MinMax;
|
|
|
|
// viewport width, height, 1/width, 1/height (scaled to the current rendertarget resolution), depends on SetViewportAndCallRHI() call
|
|
float4 ViewportSize;
|
|
// in pixels (scaled to the current rendertarget resolution), float4(minx,miny,maxx,maxy), depends on SetViewportAndCallRHI() call
|
|
uint4 ViewportRect;
|
|
|
|
// transforms ScreenPos to the screen pixel position, not the viewport local position (*xy +wz)
|
|
// (0,0) left top, (width-1,height-1) at right bottom, in pixels (without offset to reach the pixel center)
|
|
float4 ScreenPosToPixel;
|
|
|
|
float4 SceneColorBufferUVViewport;
|
|
|
|
// transform viewport UV to scene color buffer UV. As oposed to ViewportUVToBufferUV(),
|
|
// this handle viewrect change in middle of post processing caused by TAA upsample.
|
|
float2 ViewportUVToPostProcessingSceneColorBufferUV(float2 ViewportUV)
|
|
{
|
|
return ViewportUV * SceneColorBufferUVViewport.xy + SceneColorBufferUVViewport.zw;
|
|
}
|
|
|
|
// shape of the lens for vignette like effects and masking
|
|
// @param ScreenPos -1 .. 1
|
|
// @return 0..1 0:borders, 1:center
|
|
float DiscMask(float2 ScreenPos)
|
|
{
|
|
float x = saturate(1.0f - dot(ScreenPos, ScreenPos));
|
|
|
|
return x * x;
|
|
}
|
|
|
|
// black on the borders
|
|
// @param ScreenPos -1 .. 1
|
|
// @return 0..1 0:borders, 1:center
|
|
float RectMask(float2 ScreenPos)
|
|
{
|
|
float2 UV = saturate(ScreenPos * 0.5 + 0.5f);
|
|
float2 Mask2 = UV * (1 - UV);
|
|
|
|
return Mask2.x * Mask2.y * 8.0f;
|
|
}
|
|
|
|
// for rectangles with border
|
|
// @return >=0, 0 if inside
|
|
float ComputeDistanceToRect(int2 Pos, int2 LeftTop, int2 Extent, bool bRoundBorders = true)
|
|
{
|
|
int2 RightBottom = LeftTop + Extent - 1;
|
|
|
|
// use int for more precision
|
|
int2 Rel = max(int2(0, 0), Pos - RightBottom) + max(int2(0, 0), LeftTop - Pos);
|
|
|
|
if(bRoundBorders)
|
|
{
|
|
// euclidian distance (round corners)
|
|
return length((float2)Rel);
|
|
}
|
|
else
|
|
{
|
|
// manhatten distance (90 degree corners)
|
|
return max(Rel.x, Rel.y);
|
|
}
|
|
}
|
|
|
|
|
|
float3 MappingPolynomial; // RGB = a, b, c where y = a * x*x + b * x + c
|
|
|
|
// @param InLDRColor needs to be LDR (0..1) and in linear space
|
|
half3 ColorCorrection(half3 InLDRColor)
|
|
{
|
|
// final color correction to adjust for hardware differences, to make quick adjustements before a demo or simply a user setting
|
|
return MappingPolynomial.x * (InLDRColor * InLDRColor) + MappingPolynomial.y * InLDRColor + MappingPolynomial.z;
|
|
}
|
|
|
|
|
|
// Generate a mask to darken the screen borders.
|
|
// (Camera artifact and artistic effect)
|
|
// @param VignetteCircleSpacePos from VignetteSpace()
|
|
float ComputeVignetteMask(float2 VignetteCircleSpacePos, float Intensity)
|
|
{
|
|
// Natural vignetting
|
|
// cosine-fourth law
|
|
VignetteCircleSpacePos *= Intensity;
|
|
float Tan2Angle = dot( VignetteCircleSpacePos, VignetteCircleSpacePos );
|
|
float Cos4Angle = Square( rcp( Tan2Angle + 1 ) );
|
|
return Cos4Angle;
|
|
}
|
|
|
|
// Scale {-1 to 1} of the viewport space to vignette circle space.
|
|
// Vignette space is scaled such that regardless of viewport aspect ratio,
|
|
// corners are at the same brightness on a circle.
|
|
float2 VignetteSpace(float2 Pos, float AspectRatio)
|
|
{
|
|
// could be optimized but this computation should be done in the vertex shader (3 or 4 vertices)
|
|
float Scale = sqrt(2.0) / sqrt(1.0 + AspectRatio * AspectRatio);
|
|
return Pos * float2(1.0, AspectRatio) * Scale;
|
|
}
|
|
|
|
float2 VignetteSpace(float2 Pos)
|
|
{
|
|
return VignetteSpace(Pos, ViewportSize.y * ViewportSize.z);
|
|
}
|
|
|
|
half4 UnwrappedTexture3DSample( Texture2D Texture, SamplerState Sampler, float3 UVW, float Size, float InvSize )
|
|
{
|
|
// a volume texture 16x16x16 would be unwrapped to a 2d texture 256x16
|
|
|
|
float IntW = floor( UVW.z * Size - 0.5 );
|
|
half FracW = UVW.z * Size - 0.5 - IntW;
|
|
|
|
float U = ( UVW.x + IntW ) * InvSize;
|
|
float V = UVW.y;
|
|
|
|
half4 RG0 = Texture2DSample( Texture, Sampler, float2(U, V) );
|
|
half4 RG1 = Texture2DSample( Texture, Sampler, float2(U + InvSize, V) );
|
|
|
|
return lerp(RG0, RG1, FracW);
|
|
}
|
|
|
|
bool IsComputeUVOutOfBounds(in float2 UV)
|
|
{
|
|
float2 CenterDist = abs(UV - 0.5f);
|
|
return (max(CenterDist.x, CenterDist.y) >= 0.5f);
|
|
}
|
|
|
|
// Constants for DOF blend in.
|
|
half CocMaxRadiusInPixelsRcp()
|
|
{
|
|
half2 MaxOffset = half2(-2.125, -0.50) * 2.0;
|
|
return rcp(sqrt(dot(MaxOffset, MaxOffset)));
|
|
}
|
|
|
|
half2 CocBlendScaleBias()
|
|
{
|
|
half Start = 0.25 * CocMaxRadiusInPixelsRcp();
|
|
half End = 1.0 * CocMaxRadiusInPixelsRcp();
|
|
half2 ScaleBias;
|
|
ScaleBias.x = 1.0 / (End - Start);
|
|
ScaleBias.y = (-Start) * ScaleBias.x;
|
|
return ScaleBias;
|
|
}
|
|
|
|
half2 CocBlendScaleBiasFine()
|
|
{
|
|
half Start = 0.0 * CocMaxRadiusInPixelsRcp();
|
|
half End = 0.5 * CocMaxRadiusInPixelsRcp();
|
|
half2 ScaleBias;
|
|
ScaleBias.x = 1.0 / (End - Start);
|
|
ScaleBias.y = (-Start) * ScaleBias.x;
|
|
return ScaleBias;
|
|
}
|
|
|