forked from BilalY/Rasagar
256 lines
8.5 KiB
HLSL
256 lines
8.5 KiB
HLSL
#ifndef UNIVERSAL_POSTPROCESSING_COMMON_INCLUDED
|
|
#define UNIVERSAL_POSTPROCESSING_COMMON_INCLUDED
|
|
|
|
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
|
|
#include "Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blit.hlsl"
|
|
|
|
#if _FXAA
|
|
// Notes on FXAA:
|
|
// * We now rely on the official FXAA implementation (authored by Timothy Lottes while at NVIDIA)
|
|
// with minimal changes made by Unity to integrate with URP.
|
|
// * The following 'Tweakable' defines are used by the FXAA implementation and can be changed if desired:
|
|
// * FXAA_PC set to 1 is the highest quality implementation ("PC" here is a misnomer, it will run on all platforms).
|
|
// * FXAA_PC set to 0 is the cheaper 'FXAA_PC_CONSOLE' variant
|
|
// (it's equivalent to URP's old implementation but less noisy and should run faster than before)
|
|
// * FXAA_GREEN_AS_LUMA can be set to 0 for an extra performance increase but will only antialias edges that have
|
|
// some green in them (will be visually equivalent on the vast majority of scenes).
|
|
// * FXAA_QUALITY__PRESET is used when FXAA_PC is set ot 1. We chose preset 12 as it runs almost as fast on Switch as
|
|
// our old noisy implementation did.
|
|
// On all other platforms we could basically get away with preset 15 which has slightly better edge quality.
|
|
|
|
// Tweakable params (can be changed to get different performance and quality tradeoffs)
|
|
#if SHADER_API_PS5 && defined(HDR_INPUT)
|
|
// The console implementation does not generate artefacts when the input pixels are in nits (monitor HDR range).
|
|
#define FXAA_PC 0
|
|
#else
|
|
#define FXAA_PC 1
|
|
#endif
|
|
#define FXAA_GREEN_AS_LUMA 0
|
|
#define FXAA_QUALITY__PRESET 12
|
|
|
|
// Fixed params (should not be changed)
|
|
#define FXAA_HLSL_5 1
|
|
#define FXAA_GATHER4_ALPHA 0
|
|
#define FXAA_PC_CONSOLE !FXAA_PC
|
|
|
|
#include "Packages/com.unity.render-pipelines.universal/Shaders/PostProcessing/FXAA3_11.hlsl"
|
|
#endif
|
|
|
|
// ----------------------------------------------------------------------------------
|
|
// Utility functions
|
|
|
|
half GetLuminance(half3 colorLinear)
|
|
{
|
|
#if _TONEMAP_ACES
|
|
return AcesLuminance(colorLinear);
|
|
#else
|
|
return Luminance(colorLinear);
|
|
#endif
|
|
}
|
|
|
|
real3 GetSRGBToLinear(real3 c)
|
|
{
|
|
#if _USE_FAST_SRGB_LINEAR_CONVERSION
|
|
return FastSRGBToLinear(c);
|
|
#else
|
|
return SRGBToLinear(c);
|
|
#endif
|
|
}
|
|
|
|
real4 GetSRGBToLinear(real4 c)
|
|
{
|
|
#if _USE_FAST_SRGB_LINEAR_CONVERSION
|
|
return FastSRGBToLinear(c);
|
|
#else
|
|
return SRGBToLinear(c);
|
|
#endif
|
|
}
|
|
|
|
real3 GetLinearToSRGB(real3 c)
|
|
{
|
|
#if _USE_FAST_SRGB_LINEAR_CONVERSION
|
|
return FastLinearToSRGB(c);
|
|
#else
|
|
return LinearToSRGB(c);
|
|
#endif
|
|
}
|
|
|
|
real4 GetLinearToSRGB(real4 c)
|
|
{
|
|
#if _USE_FAST_SRGB_LINEAR_CONVERSION
|
|
return FastLinearToSRGB(c);
|
|
#else
|
|
return LinearToSRGB(c);
|
|
#endif
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------
|
|
// Shared functions for uber & fast path (on-tile)
|
|
// These should only process an input color, don't sample in neighbor pixels!
|
|
|
|
half3 ApplyVignette(half3 input, float2 uv, float2 center, float intensity, float roundness, float smoothness, half3 color)
|
|
{
|
|
center = UnityStereoTransformScreenSpaceTex(center);
|
|
float2 dist = abs(uv - center) * intensity;
|
|
|
|
dist.x *= roundness;
|
|
float vfactor = pow(saturate(1.0 - dot(dist, dist)), smoothness);
|
|
return input * lerp(color, (1.0).xxx, vfactor);
|
|
}
|
|
|
|
half3 ApplyTonemap(half3 input)
|
|
{
|
|
#if _TONEMAP_ACES
|
|
float3 aces = unity_to_ACES(input);
|
|
input = AcesTonemap(aces);
|
|
#elif _TONEMAP_NEUTRAL
|
|
input = NeutralTonemap(input);
|
|
#endif
|
|
|
|
return saturate(input);
|
|
}
|
|
|
|
half3 ApplyColorGrading(half3 input, float postExposure, TEXTURE2D_PARAM(lutTex, lutSampler), float3 lutParams, TEXTURE2D_PARAM(userLutTex, userLutSampler), float3 userLutParams, float userLutContrib)
|
|
{
|
|
// Artist request to fine tune exposure in post without affecting bloom, dof etc
|
|
input *= postExposure;
|
|
|
|
// HDR Grading:
|
|
// - Apply internal LogC LUT
|
|
// - (optional) Clamp result & apply user LUT
|
|
#if _HDR_GRADING
|
|
{
|
|
float3 inputLutSpace = saturate(LinearToLogC(input)); // LUT space is in LogC
|
|
input = ApplyLut2D(TEXTURE2D_ARGS(lutTex, lutSampler), inputLutSpace, lutParams);
|
|
|
|
UNITY_BRANCH
|
|
if (userLutContrib > 0.0)
|
|
{
|
|
input = saturate(input);
|
|
input.rgb = GetLinearToSRGB(input.rgb); // In LDR do the lookup in sRGB for the user LUT
|
|
half3 outLut = ApplyLut2D(TEXTURE2D_ARGS(userLutTex, userLutSampler), input, userLutParams);
|
|
input = lerp(input, outLut, userLutContrib);
|
|
input.rgb = GetSRGBToLinear(input.rgb);
|
|
}
|
|
}
|
|
|
|
// LDR Grading:
|
|
// - Apply tonemapping (result is clamped)
|
|
// - (optional) Apply user LUT
|
|
// - Apply internal linear LUT
|
|
#else
|
|
{
|
|
input = ApplyTonemap(input);
|
|
|
|
UNITY_BRANCH
|
|
if (userLutContrib > 0.0)
|
|
{
|
|
input.rgb = GetLinearToSRGB(input.rgb); // In LDR do the lookup in sRGB for the user LUT
|
|
half3 outLut = ApplyLut2D(TEXTURE2D_ARGS(userLutTex, userLutSampler), input, userLutParams);
|
|
input = lerp(input, outLut, userLutContrib);
|
|
input.rgb = GetSRGBToLinear(input.rgb);
|
|
}
|
|
|
|
input = ApplyLut2D(TEXTURE2D_ARGS(lutTex, lutSampler), input, lutParams);
|
|
}
|
|
#endif
|
|
|
|
return input;
|
|
}
|
|
|
|
half3 ApplyGrain(half3 input, float2 uv, TEXTURE2D_PARAM(GrainTexture, GrainSampler), float intensity, float response, float2 scale, float2 offset, float oneOverPaperWhite)
|
|
{
|
|
// Grain in range [0;1] with neutral at 0.5
|
|
half grain = SAMPLE_TEXTURE2D(GrainTexture, GrainSampler, uv * scale + offset).w;
|
|
|
|
// Remap [-1;1]
|
|
grain = (grain - 0.5) * 2.0;
|
|
|
|
// Noisiness response curve based on scene luminance
|
|
float lum = Luminance(input);
|
|
#ifdef HDR_INPUT
|
|
lum *= oneOverPaperWhite;
|
|
#endif
|
|
lum = 1.0 - sqrt(lum);
|
|
lum = lerp(1.0, lum, response);
|
|
|
|
return input + input * grain * intensity * lum;
|
|
}
|
|
|
|
half3 ApplyDithering(half3 input, float2 uv, TEXTURE2D_PARAM(BlueNoiseTexture, BlueNoiseSampler), float2 scale, float2 offset, float paperWhite, float oneOverPaperWhite)
|
|
{
|
|
// Symmetric triangular distribution on [-1,1] with maximal density at 0
|
|
float noise = SAMPLE_TEXTURE2D(BlueNoiseTexture, BlueNoiseSampler, uv * scale + offset).a * 2.0 - 1.0;
|
|
noise = FastSign(noise) * (1.0 - sqrt(1.0 - abs(noise)));
|
|
|
|
#if UNITY_COLORSPACE_GAMMA
|
|
input += noise / 255.0;
|
|
#elif defined(HDR_INPUT)
|
|
input = input * oneOverPaperWhite;
|
|
// Do not call GetSRGBToLinear/GetLinearToSRGB because the "fast" version will clamp values!
|
|
input = SRGBToLinear(LinearToSRGB(input) + noise / 255.0);
|
|
input = input * paperWhite;
|
|
#else
|
|
input = GetSRGBToLinear(GetLinearToSRGB(input) + noise /255.0);
|
|
#endif
|
|
|
|
return input;
|
|
}
|
|
|
|
#if _FXAA
|
|
static const FxaaFloat kSubpixelBlendAmount = 0.65;
|
|
static const FxaaFloat kRelativeContrastThreshold = 0.15;
|
|
static const FxaaFloat kAbsoluteContrastThreshold = 0.03;
|
|
#endif
|
|
|
|
half3 ApplyFXAA(half3 color, float2 positionNDC, int2 positionSS, float4 sourceSize, TEXTURE2D_X(inputTexture), float paperWhite, float oneOverPaperWhite)
|
|
{
|
|
#if _FXAA
|
|
FxaaTex tex = {sampler_LinearClamp, _BlitTexture};
|
|
FxaaFloat4 kUnusedFloat4 = FxaaFloat4(0, 0, 0, 0);
|
|
|
|
FxaaFloat4 fxaaConsolePos = 0;
|
|
FxaaFloat4 kFxaaConsoleRcpFrameOpt = 0;
|
|
FxaaFloat4 kFxaaConsoleRcpFrameOpt2 = 0;
|
|
FxaaFloat kFxaaConsoleEdgeSharpness = 0;
|
|
FxaaFloat kFxaaConsoleEdgeThreshold = 0;
|
|
FxaaFloat kFxaaConsoleEdgeThresholdMin = 0;
|
|
FxaaFloat2 fxaaHDROutputPaperWhiteNits = 0;
|
|
|
|
#if FXAA_PC_CONSOLE == 1
|
|
fxaaConsolePos = FxaaFloat4(positionNDC.xy - 0.5*sourceSize.zw, positionNDC.xy + 0.5*sourceSize.zw);
|
|
kFxaaConsoleRcpFrameOpt = 0.5*FxaaFloat4(sourceSize.zw, -sourceSize.zw);
|
|
kFxaaConsoleRcpFrameOpt2 = 2.0*FxaaFloat4(-sourceSize.zw, sourceSize.zw);
|
|
kFxaaConsoleEdgeSharpness = 8.0;
|
|
kFxaaConsoleEdgeThreshold = 0.125;
|
|
kFxaaConsoleEdgeThresholdMin = 0.05;
|
|
#endif
|
|
fxaaHDROutputPaperWhiteNits = FxaaFloat2(paperWhite, oneOverPaperWhite);
|
|
|
|
return FxaaPixelShader(
|
|
positionNDC,
|
|
FxaaFloat4(color, 0),
|
|
fxaaConsolePos,
|
|
tex,
|
|
tex,
|
|
tex,
|
|
sourceSize.zw,
|
|
kFxaaConsoleRcpFrameOpt,
|
|
kFxaaConsoleRcpFrameOpt2,
|
|
kUnusedFloat4,
|
|
kSubpixelBlendAmount,
|
|
kRelativeContrastThreshold,
|
|
kAbsoluteContrastThreshold,
|
|
kFxaaConsoleEdgeSharpness,
|
|
kFxaaConsoleEdgeThreshold,
|
|
kFxaaConsoleEdgeThresholdMin,
|
|
kUnusedFloat4,
|
|
fxaaHDROutputPaperWhiteNits
|
|
).rgb;
|
|
#else
|
|
return color;
|
|
#endif
|
|
}
|
|
|
|
#endif // UNIVERSAL_POSTPROCESSING_COMMON_INCLUDED
|