From 969153f57bbd43cc9c68a1555ebb1ebfd4044075 Mon Sep 17 00:00:00 2001 From: papadanku Date: Sun, 4 Aug 2024 09:38:40 -0700 Subject: [PATCH] cLens: Added multi-channel option --- shaders/cLens.fx | 28 ++++++++++++++--------- shaders/shared/cProcedural.fxh | 35 +++++++++++++++++++++++++++-- shaders/shared/fidelityfx/cLens.fxh | 12 +++++----- 3 files changed, 58 insertions(+), 17 deletions(-) diff --git a/shaders/cLens.fx b/shaders/cLens.fx index b7b0a75..c5cbab1 100644 --- a/shaders/cLens.fx +++ b/shaders/cLens.fx @@ -32,35 +32,42 @@ uniform float _Time < source = "timer"; >; -uniform bool _UseTimeSeed < +uniform int _GrainType < ui_category = "Grain"; - ui_label = "Use Time-Based Seed"; - ui_type = "radio"; -> = false; + ui_label = "Grain Type"; + ui_type = "combo"; + ui_items = "Single-Channel\0Multi-Channel\0"; +> = 0; uniform float _GrainScale < ui_category = "Grain"; - ui_label = "Scale"; + ui_label = "Grain Scale"; ui_type = "slider"; ui_min = 0.01; - ui_max = 20.0; + ui_max = 1.0; > = 0.01; uniform float _GrainAmount < ui_category = "Grain"; - ui_label = "Amount"; + ui_label = "Grain Amount"; ui_type = "slider"; ui_min = 0.0; - ui_max = 20.0; + ui_max = 1.0; > = 0.35; +uniform bool _UseTimeSeed < + ui_category = "Grain"; + ui_label = "Enable Time-Based Seed"; + ui_type = "radio"; +> = true; + uniform float _GrainSeed < ui_category = "Grain"; ui_label = "Seed Offset"; ui_type = "drag"; > = 0.0; -uniform float _Speed < +uniform float _GrainSeedSpeed < ui_category = "Grain"; ui_label = "Seed Speed"; ui_type = "slider"; @@ -88,12 +95,13 @@ float4 PS_Lens(CShade_VS2PS_Quad Input): SV_TARGET0 { float4 OutputColor = 1.0; float Seed = _GrainSeed; - Seed = (_UseTimeSeed) ? Seed + (rcp(1e+3 / _Time) * _Speed) : Seed; + Seed = (_UseTimeSeed) ? Seed + (rcp(1e+3 / _Time) * _GrainSeedSpeed) : Seed; FFX_Lens( OutputColor.rgb, CShade_SampleColorTex, Input.HPos.xy, Input.Tex0, + _GrainType, _GrainScale, _GrainAmount, _ChromAb, diff --git a/shaders/shared/cProcedural.fxh b/shaders/shared/cProcedural.fxh index 4522294..3fd8cca 100644 --- a/shaders/shared/cProcedural.fxh +++ b/shaders/shared/cProcedural.fxh @@ -112,11 +112,28 @@ // Calculate random hash rotation float2 Hash = CProcedural_GetHash2(I + O, Bias) * TwoPi; - float4 HashSinCos = float4(sin(Hash), cos(Hash)); + float2 HashSinCos1 = float2(sin(Hash.x), cos(Hash.x)); + float2 HashSinCos2 = float2(sin(Hash.y), cos(Hash.y)); float2 Gradient = F - O; // Calculate final dot-product - return float2(dot(HashSinCos.xz, Gradient), dot(HashSinCos.yw, Gradient)); + return float2(dot(HashSinCos1, Gradient), dot(HashSinCos2, Gradient)); + } + + float3 CProcedural_GetGradient3(float2 I, float2 F, float2 O, float Bias) + { + // Get constants + const float TwoPi = CMath_GetPi() * 2.0; + + // Calculate random hash rotation + float3 Hash = CProcedural_GetHash3(I + O, Bias) * TwoPi; + float2 HashSinCos1 = float2(sin(Hash.x), cos(Hash.x)); + float2 HashSinCos2 = float2(sin(Hash.y), cos(Hash.y)); + float2 HashSinCos3 = float2(sin(Hash.z), cos(Hash.z)); + float2 Gradient = F - O; + + // Calculate final dot-product + return float3(dot(HashSinCos1, Gradient), dot(HashSinCos2, Gradient), dot(HashSinCos3, Gradient)); } float CProcedural_GetGradientNoise1(float2 Tex, float Bias, bool Normalize) @@ -147,6 +164,20 @@ return Noise; } + float3 CProcedural_GetGradientNoise3(float2 Input, float Bias, bool Normalize) + { + float2 I = floor(Input); + float2 F = frac(Input); + float3 A = CProcedural_GetGradient3(I, F, float2(0.0, 0.0), Bias); + float3 B = CProcedural_GetGradient3(I, F, float2(1.0, 0.0), Bias); + float3 C = CProcedural_GetGradient3(I, F, float2(0.0, 1.0), Bias); + float3 D = CProcedural_GetGradient3(I, F, float2(1.0, 1.0), Bias); + float2 UV = CProcedural_GetQuintic(F); + float3 Noise = lerp(lerp(A, B, UV.x), lerp(C, D, UV.x), UV.y); + Noise = (Normalize) ? saturate((Noise * 0.5) + 0.5) : Noise; + return Noise; + } + float CProcedural_GetAntiAliasShape(float Distance, float Radius) { float AA = fwidth(Distance); diff --git a/shaders/shared/fidelityfx/cLens.fxh b/shaders/shared/fidelityfx/cLens.fxh index ed69eeb..50a5dff 100644 --- a/shaders/shared/fidelityfx/cLens.fxh +++ b/shaders/shared/fidelityfx/cLens.fxh @@ -99,6 +99,7 @@ void FFX_Lens_ApplyFilmGrain( in float2 Tex, // The input window coordinate [0, 1), [0, 1). inout float3 Color, // The current running Color, or more clearly, the sampled input Color texture Color after being modified by chromatic aberration function. + in int GrainType, // Grain formula in float GrainScaleValue, // Scaling constant value for the grain's noise frequency. in float GrainAmountValue, // Intensity constant value of the grain effect. in float GrainSeedValue // Seed value for the grain noise, for example, to change how the noise functions effect the grain frame to frame. @@ -106,11 +107,11 @@ { float2 Pos = (Tex * 2.0 - 1.0) * CShade_GetScreenSizeFromTex(Tex); float2 RandomNumberFine = CProcedural_GetHash2(Pos, 0.0); - float2 GradientN = CProcedural_GetGradientNoise2((Pos / GrainScaleValue / 8.0) + RandomNumberFine, GrainSeedValue, false); - const float GrainShape = 3.0; - - float Grain = 1.0 - 2.0 * exp2(-length(GradientN) * GrainShape); + float3 GradientN = CProcedural_GetGradientNoise3((Pos / GrainScaleValue / 8.0) + RandomNumberFine, GrainSeedValue, false); + const float GrainShape = 3.0; + float3 Grain = (GrainType == 1) ? exp2(-sqrt(abs(GradientN)) * GrainShape) : exp2(-length(GradientN) * GrainShape); + Grain = 1.0 - 2.0 * Grain; Color += Grain * min(Color, 1.0 - Color) * GrainAmountValue; } @@ -139,6 +140,7 @@ in sampler2D Image, in float2 HPos, in float2 Tex, + in int GrainType, in float GrainScale, in float GrainAmount, in float ChromAb, @@ -153,7 +155,7 @@ // Run Lens Color = FFX_Lens_SampleWithChromaticAberration(Image, HPos, Tex, Center, RGMag.r, RGMag.g); FFX_Lens_ApplyVignette(UNormTex, 0.0, Color, Vignette); - FFX_Lens_ApplyFilmGrain(Tex, Color, GrainScale, GrainAmount, GrainSeed); + FFX_Lens_ApplyFilmGrain(Tex, Color, GrainType, GrainScale, GrainAmount, GrainSeed); } #endif