diff --git a/Game/Resources_SoC_1.0006/gamedata/config/ui/ui_mm_opt.xml b/Game/Resources_SoC_1.0006/gamedata/config/ui/ui_mm_opt.xml index 9c9978f622..560fe4ca8f 100644 --- a/Game/Resources_SoC_1.0006/gamedata/config/ui/ui_mm_opt.xml +++ b/Game/Resources_SoC_1.0006/gamedata/config/ui/ui_mm_opt.xml @@ -470,7 +470,7 @@ ui_mm_ao_mode - + diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/ACES.H b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/ACES.H new file mode 100644 index 0000000000..f1d4a1d47b --- /dev/null +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/ACES.H @@ -0,0 +1,400 @@ +//================================================================================================= +// ACEScg color space and ACEScc log space transformations and Reference Rendering Transform for sRGB monitors +// Based on code by Stephen Hill (@self_shadow), Unity Technologies and others +//================================================================================================= +#define USE_ACES // Use ACES style color management +//================================================================================================= +static const float PI = 3.14159265; +static const float HALF_MIN = 6.10352e-5f; +static const float HALF_MAX = 65504; +static const float ACEScc_MAX = 1.4679964; +static const float ACEScc_MIDGRAY = 0.4135884; +// static const float3 LUMINANCE_VECTOR = float3(0.213, 0.715, 0.072); + +static const float RRT_GLOW_GAIN = 0.05; +static const float RRT_GLOW_MID = 0.08; + +static const float RRT_RED_SCALE = 0.82; +static const float RRT_RED_PIVOT = 0.03; +static const float RRT_RED_HUE = 0.0; +static const float RRT_RED_WIDTH = 135.0; + +static const float RRT_SAT_FACTOR = 0.96; + +// static const float CINEMA_WHITE = 48.0; +// static const float CINEMA_BLACK = CINEMA_WHITE / 2400.0; +static const float ODT_SAT_FACTOR = 0.93; + +static const float DIM_SURROUND_GAMMA = 0.9811; + +//================================================================================================= +// Color transformation matrices +// + +static const float3x3 sRGB_2_AP0 = {0.4397010, 0.3829780, 0.1773350, 0.0897923, 0.8134230, 0.0967616, 0.0175440, 0.1115440, 0.8707040}; + +static const float3x3 AP0_2_sRGB = { + 2.52169, -1.13413, -0.38756, -0.27648, 1.37272, -0.09624, -0.01538, -0.15298, 1.16835, +}; + +static const float3x3 sRGB_2_AP1 = {0.61319, 0.33951, 0.04737, 0.07021, 0.91634, 0.01345, 0.02062, 0.10957, 0.86961}; + +static const float3x3 AP1_2_sRGB = { + 1.70505, -0.62179, -0.08326, -0.13026, 1.14080, -0.01055, -0.02400, -0.12897, 1.15297, +}; + +static const float3x3 AP0_2_AP1 = {1.4514393161, -0.2365107469, -0.2149285693, -0.0765537734, 1.1762296998, -0.0996759264, 0.0083161484, -0.0060324498, 0.9977163014}; + +static const float3x3 AP1_2_AP0 = {0.6954522414, 0.1406786965, 0.1638690622, 0.0447945634, 0.8596711185, 0.0955343182, -0.0055258826, 0.0040252103, 1.0015006723}; + +static const float3 AP1_RGB2Y = float3(0.272229, 0.674082, 0.0536895); +/* +static const float3x3 RRT_SAT_MAT = +{ + 0.9708890, 0.0269633, 0.00214758, + 0.0108892, 0.9869630, 0.00214758, + 0.0108892, 0.0269633, 0.96214800 +}; + +static const float3x3 ODT_SAT_MAT = +{ + 0.949056, 0.0471857, 0.00375827, + 0.019056, 0.9771860, 0.00375827, + 0.019056, 0.0471857, 0.93375800 +}; +*/ +static const float3x3 AP1_2_XYZ_MAT = {0.6624541811, 0.1340042065, 0.1561876870, 0.2722287168, 0.6740817658, 0.0536895174, -0.0055746495, 0.0040607335, 1.0103391003}; + +static const float3x3 XYZ_2_AP1_MAT = {1.6410233797, -0.3248032942, -0.2364246952, -0.6636628587, 1.6153315917, 0.0167563477, 0.0117218943, -0.0082844420, 0.9883948585}; + +//================================================================================================= +// Color space transformations +// + +float3 sRGB_to_ACES(float3 x) { return mul(sRGB_2_AP0, x); } + +float3 ACES_to_sRGB(float3 x) { return mul(AP0_2_sRGB, x); } + +float3 sRGB_to_ACEScg(float3 x) { return mul(sRGB_2_AP1, x); } + +float3 ACEScg_to_sRGB(float3 x) { return mul(AP1_2_sRGB, x); } + +float3 ACEScg_to_ACES(float3 x) { return mul(AP1_2_AP0, x); } + +float3 ACES_to_ACEScg(float3 x) { return mul(AP0_2_AP1, x); } + +float lin_to_ACEScc(float x) +{ + return (x < 0.00003051757) ? (log2(0.00001525878 + x * 0.5) + 9.72) / 17.52 : (log2(x) + 9.72) / 17.52; + /* + if (x <= 0) + return -0.3584474886; + else if (x < pow(2, -15)) + return (log2( pow(2, -16) + x * 0.5) + 9.72) / 17.52; + else + return (log2(x) + 9.72) / 17.52; + */ +} + +float ACEScc_to_lin(float x) +{ + return (x < -0.3013698630) ? (exp2(x * 17.52 - 9.72) - 0.00001525878) * 2 : exp2(x * 17.52 - 9.72); + /* + if (x < -0.3013698630) + return (pow( 2, x * 17.52 - 9.72) - pow( 2, -16)) * 2; + else + return pow( 2, x * 17.52 - 9.72); + */ +} + +float3 lin_to_ACEScc(float3 x) +{ + x = clamp(x, 0, HALF_MAX); + x = float3(lin_to_ACEScc(x.r), lin_to_ACEScc(x.g), lin_to_ACEScc(x.b)); + return x; +} + +float3 ACEScc_to_lin(float3 x) +{ + x = float3(ACEScc_to_lin(x.r), ACEScc_to_lin(x.g), ACEScc_to_lin(x.b)); + x = clamp(x, 0, HALF_MAX); + return x; +} + +float3 ACES_to_ACEScc(float3 x) +{ + x = ACES_to_ACEScg(x); + x = lin_to_ACEScc(x); + return x; +} + +float3 ACEScc_to_ACES(float3 x) +{ + x = ACEScc_to_lin(x); + x = ACEScg_to_ACES(x); + return x; +} + +float3 ACEScg_to_ACEScc(float3 x) +{ + x = lin_to_ACEScc(x); + return x; +} + +float3 ACEScc_to_ACEScg(float3 x) +{ + x = ACEScc_to_lin(x); + return x; +} + +//================================================================================================= +// Various RRT approximations +// +float3 RRTAndODTFit(float3 x) +{ + x *= 1.8; + float3 a = x * (x + 0.0245786) - 0.000090537; + float3 b = x * (0.983729 * x + 0.4329510) + 0.238081; + return (a / b); +} + +float3 ACESFilm(float3 x) +{ + x *= 0.7; + float a = 2.51f; + float b = 0.03f; + float c = 2.43f; + float d = 0.59f; + float e = 0.14f; + return ((x * (a * x + b)) / (x * (c * x + d) + e)); +} + +float3 ACESUnity(float3 x) +{ + x *= 1.4; + // Luminance fitting of *RRT.a1.0.3 + ODT.Academy.RGBmonitor_100nits_dim.a1.0.3*. + // https://github.com/colour-science/colour-unity/blob/master/Assets/Colour/Notebooks/CIECAM02_Unity.ipynb + // RMSE: 0.0012846272106 + const float a = 278.5085; + const float b = 10.7772; + const float c = 293.6045; + const float d = 88.7122; + const float e = 80.6889; + return (x * (a * x + b)) / (x * (c * x + d) + e); +} + +//================================================================================================= +// Display tranformations +// +float3 ACES_IDT(float3 color) +{ + float3 aces = SRGBToLinear(color); + aces = sRGB_to_ACES(aces); + return aces; +} + +float3 XYZ_2_xyY(float3 XYZ) +{ + float divisor = max(dot(XYZ, (1.0).xxx), 1e-4); + return float3(XYZ.xy / divisor, XYZ.y); +} + +float3 xyY_2_XYZ(float3 xyY) +{ + float m = xyY.z / max(xyY.y, 1e-4); + float3 XYZ = float3(xyY.xz, (1.0 - xyY.x - xyY.y)); + XYZ.xz *= m; + return XYZ; +} + +float3 darkSurround_to_dimSurround(float3 linearCV) +{ + float3 XYZ = mul(AP1_2_XYZ_MAT, linearCV); + + float3 xyY = XYZ_2_xyY(XYZ); + xyY.z = clamp(xyY.z, 0.0, HALF_MAX); + xyY.z = pow(xyY.z, DIM_SURROUND_GAMMA); + XYZ = xyY_2_XYZ(xyY); + + return mul(XYZ_2_AP1_MAT, XYZ); +} + +float3 ACES_ODT(float3 oces) +{ + // Apply gamma adjustment to compensate for dim surround + oces = darkSurround_to_dimSurround(oces); + + // martix for ODT + // oces = mul(ODT_SAT_MAT, oces); + oces = lerp(dot(oces, AP1_RGB2Y).xxx, oces, ODT_SAT_FACTOR.xxx); + + oces = ACEScg_to_sRGB(oces); + + oces = LinearTosRGB(oces); + return saturate(oces); +} + +//================================================================================================= +// Reference Render Transform and Output Display Transform +// features glow module + +float rgb_2_saturation(float3 x) +{ + const float TINY = 1e-4; + float mi = min(min(x.r, x.g), x.b); + float ma = max(max(x.r, x.g), x.b); + return (max(ma, TINY) - max(mi, TINY)) / max(ma, 1e-2); +} + +float rgb_2_yc(float3 x) +{ + const float ycRadiusWeight = 1.75; + + // Converts RGB to a luminance proxy, here called YC + // YC is ~ Y + K * Chroma + // Constant YC is a cone-shaped surface in RGB space, with the tip on the + // neutral axis, towards white. + // YC is normalized: RGB 1 1 1 maps to YC = 1 + // + // ycRadiusWeight defaults to 1.75, although can be overridden in function + // call to rgb_2_yc + // ycRadiusWeight = 1 -> YC for pure cyan, magenta, yellow == YC for neutral + // of same value + // ycRadiusWeight = 2 -> YC for pure red, green, blue == YC for neutral of + // same value. + + float r = x.x; + float g = x.y; + float b = x.z; + float chroma = sqrt(b * (b - g) + g * (g - r) + r * (r - b)); + return (b + g + r + ycRadiusWeight * chroma) / 3.0; +} + +float sigmoid_shaper(float x) +{ + // Sigmoid function in the range 0 to 1 spanning -2 to +2. + + float t = max(1.0 - abs(x / 2.0), 0.0); + float y = 1.0 + sign(x) * (1.0 - t * t); + + return y / 2.0; +} + +float glow_fwd(float ycIn, float glowGainIn, float glowMid) +{ + float glowGainOut; + + if (ycIn <= 2.0 / 3.0 * glowMid) + glowGainOut = glowGainIn; + else if (ycIn >= 2.0 * glowMid) + glowGainOut = 0.0; + else + glowGainOut = glowGainIn * (glowMid / ycIn - 1.0 / 2.0); + + return glowGainOut; +} + +float rgb_2_hue(float3 x) +{ + // Returns a geometric hue angle in degrees (0-360) based on RGB values. + // For neutral colors, hue is undefined and the function will return a quiet NaN value. + float hue; + if (x.x == x.y && x.y == x.z) + hue = 0.0; // RGB triplets where RGB are equal have an undefined hue + else + hue = (180.0 / PI) * atan2(sqrt(3.0) * (x.y - x.z), 2.0 * x.x - x.y - x.z); + + if (hue < 0.0) + hue = hue + 360.0; + + return hue; +} + +float center_hue(float hue, float centerH) +{ + float hueCentered = hue - centerH; + if (hueCentered < -180.0) + hueCentered = hueCentered + 360.0; + else if (hueCentered > 180.0) + hueCentered = hueCentered - 360.0; + return hueCentered; +} + +float3 ACES_RRT(float3 aces) +{ + // --- Glow module --- // + float saturation = rgb_2_saturation(aces); + float ycIn = rgb_2_yc(aces); + float s = sigmoid_shaper((saturation - 0.4) / 0.2); + float addedGlow = 1.0 + glow_fwd(ycIn, RRT_GLOW_GAIN * s, RRT_GLOW_MID); + // addedGlow = (addedGlow > 1) ? 100 : 1; //check glow region + aces *= addedGlow; + + // --- Red modifier --- // + float hue = rgb_2_hue(aces); + float centeredHue = center_hue(hue, RRT_RED_HUE); + float hueWeight; + { + // hueWeight = cubic_basis_shaper(centeredHue, RRT_RED_WIDTH); + hueWeight = smoothstep(0.0, 1.0, 1.0 - abs(2.0 * centeredHue / RRT_RED_WIDTH)); + hueWeight *= hueWeight; + } + aces.r += hueWeight * saturation * (RRT_RED_PIVOT - aces.r) * (1.0 - RRT_RED_SCALE); + + // --- ACES to RGB rendering space --- // + aces = clamp(aces, 0.0, HALF_MAX); + aces = ACES_to_ACEScg(aces); + + // clamp to float range and within gamut + float3 rgbPre = clamp(aces, 0.0, HALF_MAX); + + // --- Global desaturation --- // + // rgbPre = mul(RRT_SAT_MAT, rgbPre); + rgbPre = lerp(dot(rgbPre, AP1_RGB2Y).xxx, rgbPre, RRT_SAT_FACTOR.xxx); + + float3 rgbPost; + + // various ACES RRT approximations + + // Stephen Hill - clips blacks? + // rgbPost = RRTAndODTFit(rgbPre); + + // Krzysztof Narkowicz + // rgbPost = ACESFilm(rgbPre); + + // Unity + rgbPost = ACESUnity(rgbPre); + + float3 oces = rgbPost; + + return oces; +} + +//================================================================================================= +// Look Modification Transform +// global modifiers to the image before tonemapping +// blue highlight fix is included, however it is for AP0, so using it requires 3 matrix tranforms +// +// load custom behaviours from another file +#include "ACES_LMT.h" + +//================================================================================================= +// ACES implementation +// ACEScg is the main color space, similar to the implementation in UE4 +// +float3 ACES(float3 color) +{ + // Input Display Transform into ACEScg (linear gamma space with AP1 primaries) + float3 aces = ACES_IDT(color); + + // Look Modification Transform (preset color modifications) + ACES_LMT(aces); + + // Reference Render Transform (tonemapping including the global desaturation but without the 'glow module') + float3 oces = ACES_RRT(aces); + + // Output Display Tranform into sRGB (linear gamma space with sRGB primaries) + oces = ACES_ODT(oces); + + return oces; +} \ No newline at end of file diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/ACES_Color_Grading.h b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/ACES_Color_Grading.h new file mode 100644 index 0000000000..1493dfb7c1 --- /dev/null +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/ACES_Color_Grading.h @@ -0,0 +1,52 @@ +//================================================================================================= +// Color grading - Color Decision List +// ACEScc compatible CDL https://github.com/ampas/aces-dev/blob/518c27f577e99cdecfddf2ebcfaa53444b1f9343/documents/LaTeX/S-2014-003/appendixB.tex#L1 +//================================================================================================= + +float ASC_CDL(float x, float Slope, float Offset, float Power) +{ + x *= Slope; + x += Offset; + + // ACEScc has negative values that must not be clamped + // Use this to apply power to the negative range + float IsNeg = x >= 0 ? 1 : -1; + x = abs(x); + x = pow(x, Power); + x *= IsNeg; + + return x; +} + +void Color_Grading(inout float3 aces) +{ + float3 x = aces; + + // ASC-CDL (SOP-S) style color grading + float3 Slope = {1.000, 1.000, 1.000}; + float3 Offset = {0.000, 0.000, 0.000}; + float3 Power = {1.000, 1.000, 1.000}; + float Saturation = 1; + +// load custom settings from another file +#include "ACES_settings.h" + +#ifdef USE_LOG_GRADING + // to ACEScc log space + x = lin_to_ACEScc(x); +#endif + + // apply CDL color grading + x = float3(ASC_CDL(x.r, Slope.r, Offset.r, Power.r), ASC_CDL(x.g, Slope.g, Offset.g, Power.g), ASC_CDL(x.b, Slope.b, Offset.b, Power.b)); + + // apply saturation + float luma = dot(x, LUMINANCE_VECTOR); + x = luma + Saturation * (x - luma); + +#ifdef USE_LOG_GRADING + // from ACEScc log space + x = ACEScc_to_lin(x); +#endif + + aces = x; +} \ No newline at end of file diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/ACES_LMT.h b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/ACES_LMT.h new file mode 100644 index 0000000000..a4adb20ac9 --- /dev/null +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/ACES_LMT.h @@ -0,0 +1,42 @@ +//================================================================================================= +// Look Modification Transforms +// Stackable preset color modifications (linear ACEScg in/out) +//================================================================================================= +// Console commands +// These can be used in LMTs to control their effect in engine +// RGB + Offset +// uniform float4 shader_param_1; // Slope +// uniform float4 shader_param_2; // Offset +// uniform float4 shader_param_3; // Power +// uniform float4 shader_param_4; +// uniform float4 shader_param_5; +// uniform float4 shader_param_6; +// uniform float4 shader_param_7; +// uniform float4 shader_param_8; //Used by Beef's NVGs +//================================================================================================= +#include "ACES_Color_Grading.h" +#include "ACES_LMTs\LMT_Contrast_Reduction.h" +#include "ACES_LMTs\LMT_Technicolor.h" +#include "ACES_LMTs\LMT_Bleach_Bypass.h" +#include "ACES_LMTs\LMT_Blue_Fix.h" + +void ACES_LMT(inout float3 aces) +{ +#ifdef USE_ACES + // do color grading in ACEScg primaries for more predictable results + aces = ACES_to_ACEScg(aces); +#endif + + Color_Grading(aces); + Contrast_Reduction(aces); + + // Technicolor(aces); + // Bleach_Bypass(aces); + +#ifdef USE_ACES + // Return to ACES AP0 + aces = ACEScg_to_ACES(aces); + + Blue_Fix(aces); // ACES AP0 blue color shift fix +#endif +} \ No newline at end of file diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/ACES_LMTs/LMT_Bleach_Bypass.h b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/ACES_LMTs/LMT_Bleach_Bypass.h new file mode 100644 index 0000000000..6241d77901 --- /dev/null +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/ACES_LMTs/LMT_Bleach_Bypass.h @@ -0,0 +1,38 @@ +//================================================================================================= +// LMT - Bleach Bypass by Nvidia +// Creates a highly contrasted and desaturated look +//================================================================================================= + +float Bleach_Bypass_Amount = 0.75; // strength of the effect + +void Bleach_Bypass(inout float3 aces) +{ + float3 x = aces; +#ifdef USE_ACES + x = ACEScg_to_sRGB(x); + x = max(0, x); +#endif + + x = x / (1 + x); // compress to LDR + + float4 base = float4(x.rgb, 1); // compress to LDR + float3 lumCoeff = float3(0.25, 0.65, 0.1); + float lum = dot(lumCoeff, base.rgb); + float3 blend = lum.rrr; + float L = min(1, max(0, 10 * (lum - 0.45))); + float3 result1 = 2.0f * base.rgb * blend; + float3 result2 = 1.0f - 2.0f * (1.0f - blend) * (1.0f - base.rgb); + float3 newColor = lerp(result1, result2, L); + float A2 = Bleach_Bypass_Amount * base.a; + float3 mixRGB = A2 * newColor.rgb; + mixRGB += ((1.0f - A2) * base.rgb); + mixRGB = saturate(mixRGB); + + x = mixRGB / max(0.004, 1 - mixRGB); // expand to HDR + +#ifdef USE_ACES + x = sRGB_to_ACEScg(x); +#endif + + aces = lerp(aces, x, Technicolor_Amount); +} diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/ACES_LMTs/LMT_Blue_Fix.h b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/ACES_LMTs/LMT_Blue_Fix.h new file mode 100644 index 0000000000..305bc7bc6d --- /dev/null +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/ACES_LMTs/LMT_Blue_Fix.h @@ -0,0 +1,7 @@ +//================================================================================================= +// LMT for fixing occasional image artifacts seen in bright highlights (e.g. sirens,headlights,etc.) +// Note that this will change scene colorimetry! (but tends to do so in a pleasing way) +//================================================================================================= +static const float3x3 correctionMatrix = {{0.9404372683, 0.0083786969, 0.0005471261}, {-0.0183068787, 0.8286599939, -0.0008833746}, {0.0778696104, 0.1629613092, 1.0003362486}}; + +void Blue_Fix(inout float3 aces) { aces = mul(aces, correctionMatrix); } diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/ACES_LMTs/LMT_Contrast_Reduction.h b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/ACES_LMTs/LMT_Contrast_Reduction.h new file mode 100644 index 0000000000..1038a12caf --- /dev/null +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/ACES_LMTs/LMT_Contrast_Reduction.h @@ -0,0 +1,11 @@ +//================================================================================================= +// LMT - Contrast Reduction +// Match STALKER's original tonemapping by reducing the contrast +//================================================================================================= + +void Contrast_Reduction(inout float3 aces) +{ + float Contrast_Amount = 0.7; + const float mid = 0.18; + aces = pow(aces, Contrast_Amount) * mid / pow(mid, Contrast_Amount); +} diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/ACES_LMTs/LMT_Technicolor.h b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/ACES_LMTs/LMT_Technicolor.h new file mode 100644 index 0000000000..f2dd7e18aa --- /dev/null +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/ACES_LMTs/LMT_Technicolor.h @@ -0,0 +1,42 @@ +//================================================================================================= +// LMT - Technicolor from http://enbseries.enbdev.com/forum/viewtopic.php?f=7&t=3552 +// Saturation boost that emulates the vibrancy of 3 strip technicolor +//================================================================================================= + +float Technicolor_Amount = .4; + +void Technicolor(inout float3 aces) +{ + float3 x = aces; +#ifdef USE_ACES + x = ACEScg_to_sRGB(x); + x = max(0, x); +#endif + + float3 colStrength = .4; + float brightness = 0; + + x = x / (1 + x); // compress to LDR + + float3 source = saturate(x.rgb); + float3 temp = 1 - source.rgb; + float3 target = temp.grg; + float3 target2 = temp.bbr; + float3 temp2 = source.rgb * target.rgb; + temp2.rgb *= target2.rgb; + temp.rgb = temp2.rgb * colStrength.rgb; + temp2.rgb *= brightness; + target.rgb = temp.grg; + target2.rgb = temp.bbr; + temp.rgb = source.rgb - target.rgb; + temp.rgb += temp2.rgb; + temp2.rgb = saturate(temp.rgb - target2.rgb); + + x = temp2 / max(0.004, 1 - temp2); // expand to HDR + +#ifdef USE_ACES + x = sRGB_to_ACEScg(x); +#endif + + aces = lerp(aces, x, Technicolor_Amount); +} \ No newline at end of file diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/ACES_settings.h b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/ACES_settings.h new file mode 100644 index 0000000000..da84674d65 --- /dev/null +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/ACES_settings.h @@ -0,0 +1,21 @@ +//================================================================================================= +// Defines for and variables for ACES and color grading +//================================================================================================= +#define USE_LOG_GRADING // Use log space for color grading +//================================================================================================= + +// +// manual settings +// +/* + Slope = float3(1.000, 1.000, 1.000); + Offset = float3(0.000, 0.000, 0.000); + Power = float3(1.000, 1.000, 1.000); + Saturation = 1.000; +*/ +// +// settings for supporting in-game console commands +// +Slope = pp_img_corrections.xxx; // brightness +Power = 2 * (1 - pp_img_cg.rgb); // color grading +Saturation = pp_img_corrections.z; // saturation diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/accum_base.ps b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/accum_base.ps index 31cd861ffe..cf91eaff18 100644 Binary files a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/accum_base.ps and b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/accum_base.ps differ diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/accum_emissive.ps b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/accum_emissive.ps index 0dd5896ecb..655e431d59 100644 Binary files a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/accum_emissive.ps and b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/accum_emissive.ps differ diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/accum_emissivel.ps b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/accum_emissivel.ps index 95629a7503..dc0633a359 100644 Binary files a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/accum_emissivel.ps and b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/accum_emissivel.ps differ diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/accum_indirect.ps b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/accum_indirect.ps index 4e8f2eeaf1..8111ce574b 100644 Binary files a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/accum_indirect.ps and b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/accum_indirect.ps differ diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/accum_omni_unshadowed.ps b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/accum_omni_unshadowed.ps index 5c523dbc1a..53a7a07465 100644 Binary files a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/accum_omni_unshadowed.ps and b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/accum_omni_unshadowed.ps differ diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/accum_sun.ps b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/accum_sun.ps index 70eaece5c2..005ae255dd 100644 Binary files a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/accum_sun.ps and b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/accum_sun.ps differ diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/accum_sun_far.ps b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/accum_sun_far.ps index c6c3851d0f..d69c2d3836 100644 Binary files a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/accum_sun_far.ps and b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/accum_sun_far.ps differ diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/accum_sun_mask.ps b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/accum_sun_mask.ps index d36e5b7720..441fac28de 100644 Binary files a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/accum_sun_mask.ps and b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/accum_sun_mask.ps differ diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/accum_sun_near.ps b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/accum_sun_near.ps index bfa191de61..d264cb0577 100644 Binary files a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/accum_sun_near.ps and b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/accum_sun_near.ps differ diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/accum_volumetric.ps b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/accum_volumetric.ps index c6887f0ce2..b7126a4c06 100644 Binary files a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/accum_volumetric.ps and b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/accum_volumetric.ps differ diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/bloom_luminance_3.ps b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/bloom_luminance_3.ps index 1a78b6f833..4188001fc5 100644 Binary files a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/bloom_luminance_3.ps and b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/bloom_luminance_3.ps differ diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/check_screenspace.h b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/check_screenspace.h index 54afff0e9f..0246dc1391 100644 --- a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/check_screenspace.h +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/check_screenspace.h @@ -8,4 +8,5 @@ #include "check_screenspace_FOG.h" #include "check_screenspace_IL.h" #include "check_screenspace_FLORA.h" -#include "check_screenspace_INTER_GRASS.h" \ No newline at end of file +#include "check_screenspace_INTER_GRASS.h" +#include "check_screenspace_NEWGLOSS.h" \ No newline at end of file diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/check_screenspace_ES.h b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/check_screenspace_ES.h index 29990495c6..d2e5b562a1 100644 --- a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/check_screenspace_ES.h +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/check_screenspace_ES.h @@ -1 +1 @@ -//#define SSFX_ENHANCED_SHADERS \ No newline at end of file +#define SSFX_ENHANCED_SHADERS \ No newline at end of file diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/check_screenspace_NEWGLOSS.h b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/check_screenspace_NEWGLOSS.h new file mode 100644 index 0000000000..6103880e3a --- /dev/null +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/check_screenspace_NEWGLOSS.h @@ -0,0 +1 @@ +#define SSFX_NEWGLOSS \ No newline at end of file diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/clouds.ps b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/clouds.ps index 0446e9068b..599084fd51 100644 Binary files a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/clouds.ps and b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/clouds.ps differ diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/clouds.vs b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/clouds.vs index 3a7d34dbe3..b3b7b2a36a 100644 --- a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/clouds.vs +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/clouds.vs @@ -22,8 +22,6 @@ vf main(vi v) o.hpos = mul(m_WVP, v.p); // xform, input in world coords - // if (length(float3(v.p.x,0,v.p.z))>CLOUD_FADE) o.color.w = 0 ; - // generate tcs float2 d0 = v.dir.xy * 2 - 1; float2 d1 = v.dir.wz * 2 - 1; @@ -35,9 +33,8 @@ vf main(vi v) o.color = v.color; // copy color, low precision, cannot prescale even by 2 o.color.w *= pow(v.p.y, 25); - // float scale = tex2Dlod (s_tonemap,float4(.5,.5,.5,.5)).x ; float scale = s_tonemap.Load(int3(0, 0, 0)).x; - // float scale = s_tonemap.Load( int3(1,1,0) ).x; + o.color.rgb *= scale; // high precision return o; diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/combine_1.ps b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/combine_1.ps index 7790a129a2..f8a9f4c0a9 100644 Binary files a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/combine_1.ps and b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/combine_1.ps differ diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/combine_2_naa.ps b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/combine_2_naa.ps index 304edd3b11..33dc6cd4f3 100644 Binary files a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/combine_2_naa.ps and b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/combine_2_naa.ps differ diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/combine_volumetric.s b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/combine_volumetric.s index 17e80e7b93..f01a15d382 100644 --- a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/combine_volumetric.s +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/combine_volumetric.s @@ -2,12 +2,9 @@ function normal (shader, t_base, t_second, t_detail) shader:begin ("combine_1", "combine_volumetric") : fog (false) : zb (false,false) - : blend (true,blend.one,blend.one) + : blend (true,blend.invdestcolor,blend.one) -- : aref (true,0) -- enable to save bandwith? : sorting (2, false) --- TOD0: DX10: Implement samplers --- shader:sampler ("s_vollight") :texture ("$user$generic2") --- shader:sampler ("s_tonemap") :texture ("$user$tonemap") shader:dx10texture ("s_vollight", "$user$generic2") shader:dx10texture ("s_tonemap", "$user$tonemap") diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/common_brdf.h b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/common_brdf.h index 365a2f5500..0047de5993 100644 --- a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/common_brdf.h +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/common_brdf.h @@ -19,10 +19,10 @@ #define MAT_FLORA_ELIPSON 0.04f // Simple subsurface scattering -float SSS(float3 N, float3 V, float3 L) +float3 SSS(float3 N, float3 V, float3 L) { - float S = saturate(dot(V, -(L + N))) * G_SSS_INTENSITY; - return S; + float S = saturate(dot(V, -(L + N))) * ssfx_florafixes_2.x; + return S * lerp(float3(1.0f, 1.0f, 1.0f), L_sun_color.rgb, ssfx_florafixes_2.y); } #endif diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/common_defines.h b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/common_defines.h index 1c13bbe000..f08220c6eb 100644 --- a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/common_defines.h +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/common_defines.h @@ -17,7 +17,7 @@ #define def_hdr float(9.h) // hight luminance range float(3.h) #define def_hdr_clip float(0.75h) // -#define LUMINANCE_VECTOR float3(0.3f, 0.38f, 0.22f) // anomaly: float3(0.2125, 0.7154, 0.0721) +#define LUMINANCE_VECTOR float3(0.2125, 0.7154, 0.0721) ////////////////////////////////////////////////////////////////////////////////////////// #ifndef SMAP_size diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/common_functions.h b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/common_functions.h index ed3987a385..d956e4a455 100644 --- a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/common_functions.h +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/common_functions.h @@ -1,14 +1,23 @@ #ifndef common_functions_h_included #define common_functions_h_included +#include "srgb.h" + uniform float4 m_actor_params; -float3 vibrance(float3 img, half val) +float3 vibrance(float3 img, float val) { float luminance = dot(float3(img.rgb), LUMINANCE_VECTOR); return float3(lerp(luminance, float3(img.rgb), val)); } +float2 hash22(float2 p) +{ + float3 p3 = frac(float3(p.xyx) * float3(.1031, .1030, .0973)); + p3 += dot(p3, p3.yzx + 19.19); + return frac((p3.xx + p3.yz) * p3.zy); +} + float noise(float2 tc) { return frac(sin(dot(tc, float2(12.0, 78.0) + (timers.x))) * 43758.0) * 0.25f; } // contrast function @@ -24,26 +33,53 @@ float Contrast(float Input, float ContrastPower) void tonemap(out float4 low, out float4 high, float3 rgb, float scale) { + rgb = SRGBToLinear(rgb); rgb = rgb * scale; + rgb = LinearTosRGB(rgb); - if (m_actor_params.a > 0.0f) - { - const float fWhiteIntensity = 1.7; + const float fWhiteIntensity = 11.2; - const float fWhiteIntensitySQR = fWhiteIntensity * fWhiteIntensity; + low = float4(tonemap_sRGB(rgb, fWhiteIntensity), 0); + high = float4(rgb / def_hdr, 0); +} - low = ((rgb * (1 + rgb / fWhiteIntensitySQR)) / (rgb + 1)).xyzz; +void tonemap_hipri(out float4 low, out float4 high, float3 rgb, float scale) { tonemap(low, high, rgb, scale); } - high = rgb.xyzz / def_hdr; // 8x dynamic range - } - else - { - low = rgb.xyzz; - high = low / def_hdr; // 8x dynamic range - } +// CUSTOM +float3 blend_soft(float3 a, float3 b) +{ + // return 1.0 - (1.0 - a) * (1.0 - b); + + // gamma correct and inverse tonemap to add bloom + a = SRGBToLinear(a); // post tonemap render + a = a / max(0.004, 1 - a); // inverse tonemap + // a = a / max(0.001, 1-a); //inverse tonemap + b = SRGBToLinear(b); // bloom + + // constrast reduction of ACES output + float Contrast_Amount = 0.7; + const float mid = 0.18; + a = pow(a, Contrast_Amount) * mid / pow(mid, Contrast_Amount); + + ACES_LMT(b); // color grading bloom + a += b; // bloom add + + // Boost the contrast to match ACES RRT + float Contrast_Boost = 1.42857; + a = pow(a, Contrast_Boost) * mid / pow(mid, Contrast_Boost); + + a = a / (1 + a); // tonemap + + a = LinearTosRGB(a); + return a; } -float4 combine_bloom(float3 low, float4 high) { return float4(low + high * high.a, 1.h); } +/*float4 combine_bloom(float3 low, float4 high) +{ + // return float4(low + high*high.a, 1); //add + high.rgb *= high.a; + return float4(blend_soft(low.rgb, high.rgb), 1); // screen +}*/ float calc_fogging(float4 w_pos) { return dot(w_pos, fog_plane); } diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/deffer_base_aref_bump-hq.ps b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/deffer_base_aref_bump-hq.ps index 9622d17ab6..c25fe6d369 100644 Binary files a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/deffer_base_aref_bump-hq.ps and b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/deffer_base_aref_bump-hq.ps differ diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/deffer_grass.ps b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/deffer_grass.ps index 8e6a2ae3f3..edbfea6431 100644 Binary files a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/deffer_grass.ps and b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/deffer_grass.ps differ diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/deffer_grass.vs b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/deffer_grass.vs index 52bb2d39f9..ec2d6c9254 100644 --- a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/deffer_grass.vs +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/deffer_grass.vs @@ -9,6 +9,10 @@ float4 wave; // cx,cy,cz,tm float4 dir2D; float4 array[61 * 4]; +#define SSFX_WIND_ISGRASS + +#include "screenspace_wind.h" + v2p_bumped main(v_detail v) { v2p_bumped O; @@ -20,22 +24,16 @@ v2p_bumped main(v_detail v) float4 c0 = array[i + 3]; // Transform pos to world coords - float4 pos; - pos.x = dot(m0, v.pos); - pos.y = dot(m1, v.pos); - pos.z = dot(m2, v.pos); - pos.w = 1; + float4 P; + P.x = dot(m0, v.pos); + P.y = dot(m1, v.pos); + P.z = dot(m2, v.pos); + P.w = 1; // Wave effect - float base = m1.w; - float dp = calc_cyclic(dot(pos, wave)); - float H = pos.y - base; // height of vertex (scaled) - float frac = v.misc.z * consts.x; // fractional - float inten = H * dp; - float2 result = calc_xz_wave(dir2D.xz * inten, frac); - - // Add wind - pos = float4(pos.x + result.x, pos.y, pos.z + result.y, 1); + float H = P.y - m1.w; // height of vertex (scaled) + float3 wind_result = ssfx_wind_grass(P.xyz, H, ssfx_wind_setup()); + float4 pos = float4(P.xyz + wind_result.xyz, 1); // INTERACTIVE GRASS - SSS Update 15.4 // https://www.moddb.com/mods/stalker-anomaly/addons/screen-space-shaders/ @@ -72,7 +70,7 @@ v2p_bumped main(v_detail v) // https://www.moddb.com/mods/stalker-anomaly/addons/screen-space-shaders/ // Fake Normal, Bi-Normal and Tangent - float3 N = normalize(float3(pos.x - m0.w, pos.y - m1.w + 1.0f, pos.z - m2.w)); + float3 N = normalize(float3(P.x - m0.w, P.y - m1.w + 1.0f, P.z - m2.w)); float3x3 xform = mul((float3x3)m_WV, float3x3(0, 0, N.x, 0, 0, N.y, 0, 0, N.z)); diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/deffer_impl_flat.ps b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/deffer_impl_flat.ps index 6f7ca8271b..cae14e24a8 100644 Binary files a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/deffer_impl_flat.ps and b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/deffer_impl_flat.ps differ diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/deffer_tree_branch_bump-hq.vs b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/deffer_tree_branch_bump-hq.vs index c6503d72f4..578df93562 100644 --- a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/deffer_tree_branch_bump-hq.vs +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/deffer_tree_branch_bump-hq.vs @@ -1,3 +1,11 @@ +/** + * @ Version: SCREEN SPACE SHADERS - UPDATE 19 + * @ Description: Trees - Branches/Bushes + * @ Modified time: 2023-11-07 13:27 + * @ Author: https://www.moddb.com/members/ascii1457 + * @ Mod: https://www.moddb.com/mods/stalker-anomaly/addons/screen-space-shaders + */ + #include "common.h" #include "check_screenspace.h" @@ -10,6 +18,8 @@ uniform float4 consts; // {1/quant,1/quant,???,???} uniform float4 c_scale, c_bias, wind, wave; uniform float2 c_sun; // x=*, y=+ +#include "screenspace_wind.h" + v2p_bumped main(v_tree I) { I.Nh = unpack_D3DCOLOR(I.Nh); @@ -19,18 +29,13 @@ v2p_bumped main(v_tree I) // Transform to world coords float3 pos = mul(m_xform, I.P); - // - float base = m_xform._24; // take base height from matrix - float dp = calc_cyclic(wave.w + dot(pos, (float3)wave)); - float H = pos.y - base; // height of vertex (scaled, rotated, etc.) - float frac = I.tc.z * consts.x; // fractional (or rigidity) - float inten = H * dp; // intensity - float2 result = calc_xz_wave(wind.xz * inten * 2.0f, frac); + float H = pos.y - m_xform._24; // height of vertex + float2 tc = (I.tc * consts).xy; + float3 wind_result = ssfx_wind_tree_branches(pos, H, tc.y, ssfx_wind_setup()); #ifdef USE_TREEWAVE - result = 0; + wind_result = 0; #endif - float4 w_pos = float4(pos.x + result.x, pos.y, pos.z + result.y, 1); - float2 tc = (I.tc * consts).xy; + float4 w_pos = float4(pos.xyz + wind_result.xyz, 1); // INTERACTIVE GRASS ( Bushes ) - SSS Update 15.4 // https://www.moddb.com/mods/stalker-anomaly/addons/screen-space-shaders/ diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/deffer_tree_branch_flat.vs b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/deffer_tree_branch_flat.vs index 6e09ad1c84..24371b5d5a 100644 --- a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/deffer_tree_branch_flat.vs +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/deffer_tree_branch_flat.vs @@ -12,6 +12,8 @@ uniform float4 consts; // {1/quant,1/quant,???,???} uniform float4 c_scale, c_bias, wind, wave; uniform float2 c_sun; // x=*, y=+ +#include "screenspace_wind.h" + v2p_flat main(v_tree I) { I.Nh = unpack_D3DCOLOR(I.Nh); @@ -23,18 +25,13 @@ v2p_flat main(v_tree I) // Transform to world coords float3 pos = mul(m_xform, I.P); - // - float base = m_xform._24; // take base height from matrix - float dp = calc_cyclic(wave.w + dot(pos, (float3)wave)); - float H = pos.y - base; // height of vertex (scaled, rotated, etc.) - float frac = I.tc.z * consts.x; // fractional (or rigidity) - float inten = H * dp; // intensity - float2 result = calc_xz_wave(wind.xz * inten, frac); + float H = pos.y - m_xform._24; // height of vertex + float2 tc = (I.tc * consts).xy; + float3 wind_result = ssfx_wind_tree_branches(pos, H, tc.y, ssfx_wind_setup()); #ifdef USE_TREEWAVE - result = 0; + wind_result = 0; #endif - float4 w_pos = float4(pos.x + result.x, pos.y, pos.z + result.y, 1); - float2 tc = (I.tc * consts).xy; + float4 w_pos = float4(pos.xyz + wind_result.xyz, 1); // INTERACTIVE GRASS ( Bushes ) - SSS Update 15.4 // https://www.moddb.com/mods/stalker-anomaly/addons/screen-space-shaders/ diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/deffer_tree_bump-hq.vs b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/deffer_tree_bump-hq.vs index 305b78652c..080d52551c 100644 --- a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/deffer_tree_bump-hq.vs +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/deffer_tree_bump-hq.vs @@ -1,3 +1,11 @@ +/** + * @ Version: SCREEN SPACE SHADERS - UPDATE 19 + * @ Description: Trees - Trunk + * @ Modified time: 2023-11-17 11:11 + * @ Author: https://www.moddb.com/members/ascii1457 + * @ Mod: https://www.moddb.com/mods/stalker-anomaly/addons/screen-space-shaders + */ + #include "common.h" uniform float3x4 m_xform; @@ -6,6 +14,8 @@ uniform float4 consts; // {1/quant,1/quant,???,???} uniform float4 c_scale, c_bias, wind, wave; uniform float2 c_sun; // x=*, y=+ +#include "screenspace_wind.h" + v2p_bumped main(v_tree I) { I.Nh = unpack_D3DCOLOR(I.Nh); @@ -14,18 +24,12 @@ v2p_bumped main(v_tree I) // Transform to world coords float3 pos = mul(m_xform, I.P); - - // - float base = m_xform._24; // take base height from matrix - float dp = calc_cyclic(wave.w + dot(pos, (float3)wave)); - float H = pos.y - base; // height of vertex (scaled, rotated, etc.) - float frac = I.tc.z * consts.x; // fractional (or rigidity) - float inten = H * dp; // intensity - float2 result = calc_xz_wave(wind.xz * inten, frac); + float H = pos.y - m_xform._24; // height of vertex + float2 wind_result = ssfx_wind_tree_trunk(pos, H, ssfx_wind_setup()).xy; #ifdef USE_TREEWAVE - result = 0; + wind_result = 0; #endif - float4 w_pos = float4(pos.x + result.x, pos.y, pos.z + result.y, 1); + float4 w_pos = float4(pos.x + wind_result.x, pos.y, pos.z + wind_result.y, 1); float2 tc = (I.tc * consts).xy; float hemi = clamp(I.Nh.w * c_scale.w + c_bias.w, 0.3f, 1.0f); // Limit hemi - SSS Update 14.5 // float hemi = I.Nh.w; diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/deffer_tree_bump.vs b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/deffer_tree_bump.vs index ef68e0ec47..f06e6d187e 100644 --- a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/deffer_tree_bump.vs +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/deffer_tree_bump.vs @@ -1,3 +1,11 @@ +/** + * @ Version: SCREEN SPACE SHADERS - UPDATE 19 + * @ Description: Trees - Trunk ( Burn Sections ) + * @ Modified time: 2023-11-17 10:57 + * @ Author: https://www.moddb.com/members/ascii1457 + * @ Mod: https://www.moddb.com/mods/stalker-anomaly/addons/screen-space-shaders + */ + #include "common.h" uniform float3x4 m_xform; @@ -6,33 +14,29 @@ uniform float4 consts; // {1/quant,1/quant,???,???} uniform float4 c_scale, c_bias, wind, wave; uniform float2 c_sun; // x=*, y=+ +#include "screenspace_wind.h" + v2p_bumped main(v_tree I) { I.Nh = unpack_D3DCOLOR(I.Nh); I.T = unpack_D3DCOLOR(I.T); I.B = unpack_D3DCOLOR(I.B); - // Transform to world coords float3 pos = mul(m_xform, I.P); - - // - float base = m_xform._24; // take base height from matrix - float dp = calc_cyclic(wave.w + dot(pos, (float3)wave)); - float H = pos.y - base; // height of vertex (scaled, rotated, etc.) - float frac = I.tc.z * consts.x; // fractional (or rigidity) - float inten = H * dp; // intensity - float2 result = calc_xz_wave(wind.xz * inten, frac); + float H = pos.y - m_xform._24; // height of vertex + float2 wind_result = ssfx_wind_tree_trunk(pos, H, ssfx_wind_setup()).xy; #ifdef USE_TREEWAVE - result = 0; + wind_result = 0; #endif - float4 w_pos = float4(pos.x + result.x, pos.y, pos.z + result.y, 1); + float4 w_pos = float4(pos.x + wind_result.x, pos.y, pos.z + wind_result.y, 1); float2 tc = (I.tc * consts).xy; float hemi = I.Nh.w * c_scale.w + c_bias.w; - // float hemi = I.Nh.w; + // float hemi = I.Nh.w; // Eye-space pos/normal v2p_bumped O; float3 Pe = mul(m_V, w_pos); + // float3 Pe = mul(m_V, float4(pos.xyz,1)); O.tcdh = float4(tc.xyyy); O.hpos = mul(m_VP, w_pos); O.position = float4(Pe, hemi); @@ -44,11 +48,35 @@ v2p_bumped main(v_tree I) // Calculate the 3x3 transform from tangent space to eye-space // TangentToEyeSpace = object2eye * tangent2object - // = object2eye * transpose(object2tangent) (since the inverse of a rotation is its transpose) + // = object2eye * transpose(object2tangent) (since the inverse of a rotation is its transpose) // Normal mapping - float3 N = unpack_bx4(I.Nh); - float3 T = unpack_bx4(I.T); - float3 B = unpack_bx4(I.B); + float3 N = unpack_bx2(I.Nh); // just scale (assume normal in the -.5f, .5f) + float3 sphereOffset = float3(0.1, 1.0, 0.2); + float3 sphereScale = float3(1.0, 2.0, 1.0); + float3 sphereN = normalize(sphereScale * I.P.xyz + sphereOffset); // Spherical normals trick + float3 T = unpack_bx2(I.T); // + float3 B = unpack_bx2(I.B); // + N = normalize(N); + B = normalize(B); + T = normalize(T); + + // tangent basis + float3 flatB = float3(0, 0, 1); + + if (abs(dot(sphereN, flatB)) > 0.99f) + flatB = float3(0, 1, 0); + + float3 flatT = normalize(cross(sphereN, flatB)); + flatB = normalize(cross(sphereN, flatT)); + + // foliage + float foliageMat = 0.5; // foliage + // float foliageMask = saturate(abs(xmaterial-foliageMat)-0.02); //foliage + float foliageMask = (abs(xmaterial - foliageMat) >= 0.2) ? 1 : 0; // foliage + // float foliageMask = 1; //foliage + N = normalize(lerp(N, sphereN, foliageMask)); // blend to foliage normals + // B = normalize(lerp(B, flatB, foliageMask)); //blend to foliage normals + // T = normalize(lerp(T, flatT, foliageMask)); //blend to foliage normals float3x3 xform = mul((float3x3)m_xform_v, float3x3(T.x, B.x, N.x, T.y, B.y, N.y, T.z, B.z, N.z)); diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/deffer_tree_flat.vs b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/deffer_tree_flat.vs index 6ded31c7de..fe491cb878 100644 --- a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/deffer_tree_flat.vs +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/deffer_tree_flat.vs @@ -29,13 +29,35 @@ v2p_flat main(v_tree I) #endif float4 f_pos = float4(pos.x + result.x, pos.y, pos.z + result.y, 1); + // Normal mapping + float3 N = unpack_bx2(I.Nh); + float3 sphereOffset = float3(0.0, 1.0, 0.0); + float3 sphereScale = float3(1.0, 2.0, 1.0); + float3 sphereN = normalize(sphereScale * I.P.xyz + sphereOffset); // Spherical normals trick + float3 flatN = (float3(0, 1, 0)); + /* + float3 camFacingN = normalize((f_pos - eye_position.xyz) * float3(-1,0,-1)); + sphereN = lerp(camFacingN, sphereN, saturate(H)); //roots face the camera, the tips face the sky + + sphereN.xz *= 0.5; + sphereN.y = sqrt(1 - saturate(dot(sphereN.xz, sphereN.xz))); + sphereN = normalize(sphereN); + */ + // foliage + float foliageMat = 0.5; // foliage + // float foliageMask = saturate(abs(xmaterial-foliageMat)-0.02); //foliage + float foliageMask = (abs(xmaterial - foliageMat) >= 0.2) ? 1 : 0; // foliage + // float foliageMask = 1; //foliage + N = normalize(lerp(N, sphereN, foliageMask)); // blend to foliage normals + // Final xform(s) // Final xform float3 Pe = mul(m_V, f_pos); + // float3 Pe = mul(m_V, float4(pos.xyz,1)); float hemi = I.Nh.w * c_scale.w + c_bias.w; - // float hemi = I.Nh.w; + // float hemi = I.Nh.w; o.hpos = mul(m_VP, f_pos); - o.N = mul((float3x3)m_xform_v, unpack_bx2(I.Nh)); + o.N = mul((float3x3)m_xform_v, N); o.tcdh = float4((I.tc * consts).xyyy); o.position = float4(Pe, hemi); diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/deffer_tree_s_bump.vs b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/deffer_tree_s_bump.vs index 46a8cc0a2f..2ddc796799 100644 --- a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/deffer_tree_s_bump.vs +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/deffer_tree_s_bump.vs @@ -1,2 +1,101 @@ -#define USE_TREEWAVE -#include "deffer_tree_bump.vs" +#include "common.h" + +uniform float3x4 m_xform; +uniform float3x4 m_xform_v; +uniform float4 consts; // {1/quant,1/quant,???,???} +uniform float4 c_scale, c_bias, wind, wave; +uniform float2 c_sun; // x=*, y=+ + +v2p_bumped main(v_tree I) +{ + I.Nh = unpack_D3DCOLOR(I.Nh); + I.T = unpack_D3DCOLOR(I.T); + I.B = unpack_D3DCOLOR(I.B); + + // Transform to world coords + float3 pos = mul(m_xform, I.P); + float H = I.P; + + // + float2 result = 0; + float4 w_pos = float4(pos.x + result.x, pos.y, pos.z + result.y, 1); + float2 tc = (I.tc * consts).xy; + float hemi = I.Nh.w * c_scale.w + c_bias.w; + // float hemi = I.Nh.w; + + // Eye-space pos/normal + v2p_bumped O; + float3 Pe = mul(m_V, w_pos); + // float3 Pe = mul(m_V, float4(pos.xyz,1)); + O.tcdh = float4(tc.xyyy); + O.hpos = mul(m_VP, w_pos); + O.position = float4(Pe, hemi); + +#if defined(USE_R2_STATIC_SUN) && !defined(USE_LM_HEMI) + float suno = I.Nh.w * c_sun.x + c_sun.y; + O.tcdh.w = suno; // (,,,dir-occlusion) +#endif + + // Calculate the 3x3 transform from tangent space to eye-space + // TangentToEyeSpace = object2eye * tangent2object + // = object2eye * transpose(object2tangent) (since the inverse of a rotation is its transpose) + float3 N = unpack_bx2(I.Nh); // just scale (assume normal in the -.5f, .5f) + float3 T = unpack_bx2(I.T); // + float3 B = unpack_bx2(I.B); // + N = normalize(N); + B = normalize(B); + T = normalize(T); + + float3 sphereOffset = float3(0.0, 1.0, 0.0); + float3 sphereScale = float3(1.0, 2.0, 1.0); + float3 sphereN = normalize(sphereScale * I.P.xyz + sphereOffset); // Spherical normals trick + /* + float3 camFacingN = normalize((w_pos - eye_position.xyz) * float3(-1,0,-1)); + sphereN = lerp(camFacingN, sphereN, saturate(H)); //roots face the camera, the tips face the sky + + sphereN.xz *= 0.5; + sphereN.y = sqrt(1 - saturate(dot(sphereN.xz, sphereN.xz))); + sphereN = normalize(sphereN); + */ + + // tangent basis + float3 flatB = float3(0, 0, 1); + + if (abs(dot(sphereN, flatB)) > 0.99f) + flatB = float3(0, 1, 0); + + float3 flatT = normalize(cross(sphereN, flatB)); + flatB = normalize(cross(sphereN, flatT)); + + // foliage + float foliageMat = 0.5; // foliage + // float foliageMask = saturate(abs(xmaterial-foliageMat)-0.02); //foliage + float foliageMask = (abs(xmaterial - foliageMat) >= 0.2) ? 1 : 0; // foliage + // float foliageMask = 1; //foliage + N = normalize(lerp(N, sphereN, foliageMask)); // blend to foliage normals + // B = normalize(lerp(B, flatB, foliageMask)); //blend to foliage normals + // T = normalize(lerp(T, flatT, foliageMask)); //blend to foliage normals + + float3x3 xform = mul((float3x3)m_xform_v, float3x3(T.x, B.x, N.x, T.y, B.y, N.y, T.z, B.z, N.z)); + + // The pixel shader operates on the bump-map in [0..1] range + // Remap this range in the matrix, anyway we are pixel-shader limited :) + // ...... [ 2 0 0 0] + // ...... [ 0 2 0 0] + // ...... [ 0 0 2 0] + // ...... [-1 -1 -1 1] + // issue: strange, but it's slower :( + // issue: interpolators? dp4? VS limited? black magic? + + // Feed this transform to pixel shader + O.M1 = xform[0]; + O.M2 = xform[1]; + O.M3 = xform[2]; + +#ifdef USE_TDETAIL + O.tcdbump = O.tcdh * dt_params; // dt tc +#endif + + return O; +} +FXVS; diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/deffer_tree_s_flat.vs b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/deffer_tree_s_flat.vs index 7661ad3264..3596e5f938 100644 --- a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/deffer_tree_s_flat.vs +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/deffer_tree_s_flat.vs @@ -1,2 +1,67 @@ -#define USE_TREEWAVE -#include "deffer_tree_flat.vs" +#include "common.h" + +uniform float3x4 m_xform; +uniform float3x4 m_xform_v; +uniform float4 consts; // {1/quant,1/quant,???,???} +uniform float4 c_scale, c_bias, wind, wave; +uniform float2 c_sun; // x=*, y=+ + +v2p_flat main(v_tree I) +{ + I.Nh = unpack_D3DCOLOR(I.Nh); + I.T = unpack_D3DCOLOR(I.T); + I.B = unpack_D3DCOLOR(I.B); + + v2p_flat o; + + // Transform to world coords + float3 pos = mul(m_xform, I.P); + float H = I.P; + + // + float2 result = 0; + float4 f_pos = float4(pos.x + result.x, pos.y, pos.z + result.y, 1); + + // Normal mapping + float3 N = unpack_bx2(I.Nh); + float3 sphereOffset = float3(0.0, 1.0, 0.0); + float3 sphereScale = float3(1.0, 2.0, 1.0); + float3 sphereN = normalize(sphereScale * I.P.xyz + sphereOffset); // Spherical normals trick + float3 flatN = (float3(0, 1, 0)); + /* + float3 camFacingN = normalize((f_pos - eye_position.xyz) * float3(-1,0,-1)); + sphereN = lerp(camFacingN, sphereN, saturate(H)); //roots face the camera, the tips face the sky + + sphereN.xz *= 0.5; + sphereN.y = sqrt(1 - saturate(dot(sphereN.xz, sphereN.xz))); + sphereN = normalize(sphereN); + */ + // foliage + float foliageMat = 0.5; // foliage + // float foliageMask = saturate(abs(xmaterial-foliageMat)-0.02); //foliage + float foliageMask = (abs(xmaterial - foliageMat) >= 0.2) ? 1 : 0; // foliage + // float foliageMask = 1; //foliage + N = normalize(lerp(N, sphereN, foliageMask)); // blend to foliage normals + + // Final xform(s) + float3 Pe = mul(m_V, f_pos); + // float3 Pe = mul(m_V, float4(pos.xyz,1)); + float hemi = I.Nh.w * c_scale.w + c_bias.w; + // float hemi = I.Nh.w; + o.hpos = mul(m_VP, f_pos); + o.N = mul((float3x3)m_xform_v, N); + o.tcdh = float4((I.tc * consts).xyyy); + o.position = float4(Pe, hemi); + +#if defined(USE_R2_STATIC_SUN) && !defined(USE_LM_HEMI) + float suno = I.Nh.w * c_sun.x + c_sun.y; + o.tcdh.w = suno; // (,,,dir-occlusion) +#endif + +#ifdef USE_TDETAIL + o.tcdbump = o.tcdh * dt_params; // dt tc +#endif + + return o; +} +FXVS; diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/details_blend.s b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/details_blend.s index c87f9097cb..8a0c1c533d 100644 --- a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/details_blend.s +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/details_blend.s @@ -9,8 +9,14 @@ function normal (shader, t_base, t_second, t_detail) shader:dx10cullmode (1) shader:dx10texture("s_base", t_base) + --local opt = shader:dx10Options() + --shader:dx10texture("s_bump", "levels\\" .. opt:getLevel() .. "\\" .. t_base.."_bump") shader:dx10texture("s_bump", t_base.."_bump") shader:dx10texture("s_bumpX", t_base.."_bump#") + + shader:dx10texture("s_waves", "fx\\wind_wave") shader:dx10sampler("smp_base") + shader:dx10sampler("smp_linear") + shader:dx10sampler("smp_linear2") end \ No newline at end of file diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/hmodel.h b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/hmodel.h index ca0dd09284..711e1f9c7f 100644 --- a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/hmodel.h +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/hmodel.h @@ -1,80 +1,135 @@ +/** + * @ Description: Enhanced Shaders and Color Grading 1.10 + * @ Author: https://www.moddb.com/members/kennshade + * @ Mod: https://www.moddb.com/mods/stalker-anomaly/addons/enhanced-shaders-and-color-grading-for-151 + */ + #ifndef HMODEL_H #define HMODEL_H +#define CUBE_MIPS 6 // mipmaps for ambient shading and specular -#include "common.h" +#include "pbr_cubemap_check.h" +// gamma correction is set up to be semi gamma correct TextureCube env_s0; TextureCube env_s1; -uniform float4 env_color; // color.w = lerp factor -uniform float3x4 m_v2w; +uniform float4 env_color; // color.w = lerp factor -void hmodel(out float3 hdiffuse, out float3 hspecular, float m, float h, float s, float3 Pnt, float3 normal) +void hmodel(out float3 hdiffuse, out float3 hspecular, float m, float h, float4 alb_gloss, float3 Pnt, float3 normal) { - // hscale - something like diffuse reflection - float3 nw = mul(m_v2w, normal); - float hscale = h; //. * (.5h + .5h*nw.y); + // [ SSS Test ]. Overwrite terrain material + bool m_terrain = abs(m - 0.95) <= 0.04f; + bool m_flora = abs(m - 0.15) <= 0.04f; + if (m_terrain) + m = 0; + + // PBR style + float3 albedo = calc_albedo(alb_gloss, m); + float3 specular = calc_specular(alb_gloss, m); + float rough = calc_rough(alb_gloss, m); + // calc_rain(albedo, specular, rough, alb_gloss, m, h); + // calc_foliage(albedo, specular, rough, float4(0.05,0.05,0.05,0.05), m); + + float roughCube = rough; + // float roughCube = sqrt(rough); //cubemap mipmaps (brdf too?) + + // float RoughMip = roughCube * CUBE_MIPS; + float RoughMip = CUBE_MIPS - ((1 - roughCube) * CUBE_MIPS); + + // normal vector + normal = normalize(normal); + float3 nw = mul(m_inv_V, normal); + // nw = normalize(nw); -#ifdef USE_GAMMA_22 - hscale = (hscale * hscale); // make it more linear -#endif + // view vector + Pnt = normalize(Pnt); + float3 v2Pnt = mul(m_inv_V, Pnt); + // v2Pnt = normalize(v2Pnt); + + // normal remap + float3 nwRemap = nw; + float3 vnormabs = abs(nwRemap); + float vnormmax = max(vnormabs.x, max(vnormabs.y, vnormabs.z)); + nwRemap /= vnormmax; + if (nwRemap.y < 0.999) + nwRemap.y = nwRemap.y * 2 - 1; // fake remapping // reflection vector - float3 v2PntL = normalize(Pnt); - float3 v2Pnt = mul(m_v2w, v2PntL); float3 vreflect = reflect(v2Pnt, nw); - float hspec = .5h + .5h * dot(vreflect, v2Pnt); - // material // sample material - float4 light = s_material.SampleLevel(smp_material, float3(hscale, hspec, m), 0).xxxy; + // reflect remap + float3 vreflectRemap = vreflect; + float3 vreflectabs = abs(vreflectRemap); + float vreflectmax = max(vreflectabs.x, max(vreflectabs.y, vreflectabs.z)); + vreflectRemap /= vreflectmax; + if (vreflectRemap.y < 0.999) + vreflectRemap.y = vreflectRemap.y * 2 - 1; // fake remapping + + // normalize + nwRemap = normalize(nwRemap); + vreflectRemap = normalize(vreflectRemap); + + // DICE reflection vector roughness + vreflectRemap = getSpecularDominantDir(nwRemap, vreflectRemap, rough); + + // Valve style ambient cube to prevent seams + const float Epsilon = 0.001; + float3 nSquared = nw * nw; - // diffuse color - // float3 e0d = texCUBE( env_s0, nw ); - // float3 e1d = texCUBE( env_s1, nw ); - // float3 e0d = env_s0.Sample( smp_rtlinear, nw ); - // float3 e1d = env_s1.Sample( smp_rtlinear, nw ); - float3 e0d = env_s0.SampleLevel(smp_rtlinear, nw, 0); - float3 e1d = env_s1.SampleLevel(smp_rtlinear, nw, 0); - float3 env_d = env_color.xyz * lerp(e0d, e1d, env_color.w); - env_d *= env_d; // contrast - hdiffuse = env_d * light.xyz + L_ambient.rgb; + float3 e0d = 0; + e0d += nSquared.x * (env_s0.SampleLevel(smp_base, float3(nwRemap.x, Epsilon, Epsilon), CUBE_MIPS).rgb); + e0d += nSquared.y * (env_s0.SampleLevel(smp_base, float3(Epsilon, nwRemap.y, Epsilon), CUBE_MIPS).rgb); + e0d += nSquared.z * (env_s0.SampleLevel(smp_base, float3(Epsilon, Epsilon, nwRemap.z), CUBE_MIPS).rgb); + // e0d = LinearTosRGB(e0d); + + // e0d = env_s0.SampleLevel(smp_base, nwRemap, CUBE_MIPS); + + float3 e1d = 0; + e1d += nSquared.x * (env_s1.SampleLevel(smp_base, float3(nwRemap.x, Epsilon, Epsilon), CUBE_MIPS).rgb); + e1d += nSquared.y * (env_s1.SampleLevel(smp_base, float3(Epsilon, nwRemap.y, Epsilon), CUBE_MIPS).rgb); + e1d += nSquared.z * (env_s1.SampleLevel(smp_base, float3(Epsilon, Epsilon, nwRemap.z), CUBE_MIPS).rgb); + // e1d = LinearTosRGB(e1d); + + // e1d = env_s1.SampleLevel(smp_base, nwRemap, CUBE_MIPS); // specular color - vreflect.y = vreflect.y * 2 - 1; // fake remapping - // float3 e0s = texCUBE( env_s0, vreflect ); - // float3 e1s = texCUBE( env_s1, vreflect ); - // float3 e0s = env_s0.Sample( smp_rtlinear, vreflect ); - // float3 e1s = env_s1.Sample( smp_rtlinear, vreflect ); - float3 e0s = env_s0.SampleLevel(smp_rtlinear, vreflect, 0); - float3 e1s = env_s1.SampleLevel(smp_rtlinear, vreflect, 0); - float3 env_s = env_color.xyz * lerp(e0s, e1s, env_color.w); - env_s *= env_s; // contrast - hspecular = env_s * light.w * s; //*h*m*s ; //env_s *light.w * s; -} + float3 e0s = env_s0.SampleLevel(smp_base, vreflectRemap, RoughMip); + float3 e1s = env_s1.SampleLevel(smp_base, vreflectRemap, RoughMip); -/* -void hmodel_table (out float3 hdiffuse, out float3 hspecular, float m, float h, float s, float3 point, float3 normal) -{ - // hscale - something like diffuse reflection - float hscale = h; + // lerp + float3 env_d = lerp(e0d, e1d, env_color.w); + float3 env_s = lerp(e0s, e1s, env_color.w); + + // hscale - something like diffuse reflection + float hscale = h; //. * (.5h + .5h*nw.y); + float hspec = .5h + .5h * dot(vreflect, v2Pnt); + + // TODO - make hscale normal mapped + float4 light = float4(hscale, hscale, hscale, hscale); + // float4 light = s_material.SampleLevel( smp_material, float3( hscale, hspec, m ), 0 ).xxxy; + + // tint color + // float3 env_col = 1.0; + float3 env_col = env_color.rgb; + // float3 env_col = fog_color.rgb * 2.0; - // reflection vector - float3 v2point = normalize (Pnt); - float3 vreflect= reflect (v2point,normal); - float hspec = .5h+.5h*dot (vreflect,v2point); + env_d *= env_col; + env_s *= env_col; - // material - float4 light = tex3D (s_material, float3(hscale, hspec, m) ); // sample material + // lightmap ambient + env_d *= light.xxx; + env_s *= light.www; - // diffuse color - float3 env_d = texCUBE (env_s0,normal); + // ambient color + float3 amb_col = L_ambient.rgb; + env_d += amb_col; + env_s += amb_col; //*(env_s/env_d); - // specular color - float3 env_s = texCUBE (env_s0,vreflect); + env_d = SRGBToLinear(env_d); + env_s = SRGBToLinear(env_s); // gamma correct - // - hdiffuse = env_d *light.xyz + L_ambient.rgb ; - hspecular = env_s *light.w * s ; + hdiffuse = Amb_BRDF(rough, albedo, specular, env_d, env_s * !m_flora, -v2Pnt, nw).rgb; + hspecular = 0; // do not use hspec at all } -*/ #endif \ No newline at end of file diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/img_corrections.h b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/img_corrections.h new file mode 100644 index 0000000000..8f9f7b4c53 --- /dev/null +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/img_corrections.h @@ -0,0 +1,37 @@ +// DISABLED FOR ACES + +#ifndef IMG_CORRECTIONS_H +#define IMG_CORRECTIONS_H +#include "common.h" +//#include "anomaly_shaders.h" +#define COLOR_GRADING_LUMINANCE float3(0.213, 0.715, 0.072) +float3 img_corrections(float3 img) +{ + /* + //exposure + img.xyz *= pp_img_corrections.x; + + //do color in tonemap + //color grading (thanks KD and Crytek) + float fLum = dot(img.xyz, COLOR_GRADING_LUMINANCE)*2; + float3 cMin = 0.0; + float3 cMed = pp_img_cg.xyz; + float3 cMax = 1.0; + float3 cColor = lerp(cMin, cMed , saturate(fLum * 2.0 ) ); + cColor = lerp(cColor, cMax, saturate(fLum - 0.5 ) * 2.0 ); + + //if (pp_img_cg.x > 0.0 || pp_img_cg.y > 0.0 || pp_img_cg.z > 0.0) + { + img.xyz = saturate(lerp(img.xyz, cColor.xyz , saturate(fLum * 0.15f ) )); + } + + //saturation + img.xyz = max(0, lerp(img.xyz, dot(img.xyz, LUMINANCE_VECTOR), (1.0 - pp_img_corrections.z))); + */ + // gamma correction + img.xyz = pow(img, (1. / pp_img_corrections.y)); + + // that's all :) + return img.xyz; +} +#endif \ No newline at end of file diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/lmodel.h b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/lmodel.h index 9da7865a45..880346a27b 100644 --- a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/lmodel.h +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/lmodel.h @@ -1,58 +1,101 @@ +/** + * @ Description: Enhanced Shaders and Color Grading 1.10 + * @ Author: https://www.moddb.com/members/kennshade + * @ Mod: https://www.moddb.com/mods/stalker-anomaly/addons/enhanced-shaders-and-color-grading-for-151 + */ + #ifndef LMODEL_H #define LMODEL_H #include "common.h" #include "common_brdf.h" +#include "pbr_brdf.h" ////////////////////////////////////////////////////////////////////////////////////////// // Lighting formulas -float4 compute_lighting(float3 N, float3 V, float3 L, float mat_id) + +float4 compute_lighting(float3 N, float3 V, float3 L, float4 alb_gloss, float mat_id) { - // Half vector - float3 H = normalize(L + V); + // [ SSS Test ]. Overwrite terrain material + bool m_terrain = abs(mat_id - 0.95) <= 0.04f; + if (m_terrain) + mat_id = 0; + + float3 albedo = calc_albedo(alb_gloss, mat_id); + float3 specular = calc_specular(alb_gloss, mat_id); + float rough = calc_rough(alb_gloss, mat_id); + // calc_rain(albedo, specular, rough, alb_gloss, mat_id, 1); + calc_foliage(albedo, specular, rough, alb_gloss, mat_id); - // Combined light - float4 light = s_material.Sample(smp_material, float3(dot(L, N), dot(H, N), mat_id)).xxxy; + float3 light = Lit_BRDF(rough, albedo, specular, V, N, L); - if (mat_id == MAT_FLORA) // Be aware of precision loss/errors + // if(mat_id == MAT_FLORA) //Be aware of precision loss/errors + if (abs(mat_id - MAT_FLORA) <= MAT_FLORA_ELIPSON) // Be aware of precision loss/errors { // Simple subsurface scattering - float subsurface = SSS(N, V, L); - light.rgb += subsurface; + float3 subsurface = SSS(N, V, L); + light.rgb += subsurface * albedo; } - return light; + return float4(light, 0); } -float4 plight_infinity(float m, float3 pnt, float3 normal, float3 light_direction) +float4 plight_infinity(float m, float3 pnt, float3 normal, float4 c_tex, float3 light_direction) { // gsc vanilla stuff float3 N = normalize(normal); // normal - float3 V = -normalize(pnt); // vector2eye - float3 L = -normalize(light_direction); // vector2light + float3 V = normalize(-pnt); // vector2eye + float3 L = normalize(-light_direction); // vector2light - float4 light = compute_lighting(N, V, L, m); + float4 light = compute_lighting(N, V, L, c_tex, m); - return light * 2.0f / 3.0f; // output (albedo.gloss) + return light; // output (albedo.gloss) } -float4 plight_local(float m, float3 pnt, float3 normal, float3 light_position, float light_range_rsq, out float rsqr) +float4 plight_local(float m, float3 pnt, float3 normal, float4 c_tex, float3 light_position, float light_range_rsq, out float rsqr) { - float3 N = normalize(normal); // normal + float atteps = 0.1; + float3 L2P = pnt - light_position; // light2point - float3 V = -normalize(pnt); // vector2eye - float3 L = -normalize((float3)L2P); // vector2light - float3 H = normalize(L + V); // half-angle-vector rsqr = dot(L2P, L2P); // distance 2 light (squared) - float att = saturate(1 - rsqr * light_range_rsq); // q-linear attenuate + rsqr = max(rsqr, atteps); + // rsqr = rsqr + 1.0; - float4 light = compute_lighting(N, V, L, m); + // vanilla atten - linear + float att = saturate(1.0 - rsqr * light_range_rsq); // q-linear attenuate + att = SRGBToLinear(att); + /* + //unity atten - quadtratic + //catlikecoding.com/unity/tutorials/custom-srp/point-and-spot-lights/ + att = rsqr * light_range_rsq; + att *= att; + att = saturate(1.0 - att); + att *= att; + att = att / rsqr; + */ + float3 N = normalize(normal); // normal + float3 V = normalize(-pnt); // vector2eye + float3 L = normalize(-L2P); // vector2light - return att * light * 2.0f / 3.0f; // output (albedo.gloss) + float4 light = compute_lighting(N, V, L, c_tex, m); + + return att * light; // output (albedo.gloss) +} + +float3 specular_phong(float3 pnt, float3 normal, float3 light_direction) +{ + float3 H = normalize(pnt + light_direction); + float nDotL = saturate(dot(normal, light_direction)); + float nDotH = saturate(dot(normal, H)); + float nDotV = saturate(dot(normal, pnt)); + float lDotH = saturate(dot(light_direction, H)); + // float vDotH = saturate(dot(pnt, H)); + return L_sun_color.rgb * Lit_Specular(nDotL, nDotH, nDotV, lDotH, 0.02, 0.1); } // TODO: DX10: Remove path without blending -float4 blendp(float4 value, float4 tcp) { return value; } -float4 blend(float4 value, float2 tc) { return value; } +half4 blendp(half4 value, float4 tcp) { return value; } + +half4 blend(half4 value, float2 tc) { return value; } #endif \ No newline at end of file diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/models_compscreen.s b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/models_compscreen.s index d1e89ee8cd..34d0234fb9 100644 --- a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/models_compscreen.s +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/models_compscreen.s @@ -11,8 +11,11 @@ function normal (shader, t_base, t_second, t_detail) end function l_special (shader, t_base, t_second, t_detail) - shader:begin ("shadow_direct_model", "accum_emissivel") + shader:begin ("deffer_model_flat", "accum_emissivel") : zb (true,false) : fog (false) : emissive (true) + + shader:dx10texture ("s_base", t_base) + shader:dx10sampler ("smp_base") end diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/models_detector_3.ps b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/models_detector_3.ps index cfc0d3cd4d..03790d197e 100644 Binary files a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/models_detector_3.ps and b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/models_detector_3.ps differ diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/models_detector_3.s b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/models_detector_3.s index 789a36eceb..e620304281 100644 --- a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/models_detector_3.s +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/models_detector_3.s @@ -18,7 +18,9 @@ function l_special(shader, t_base, t_second, t_detail) :zb(true, false) :fog(false) :emissive(true) + shader:dx10texture("s_base", t_base) + shader:dx10sampler("smp_base") shader:dx10texture("s_numbers", t_numbers) shader:dx10sampler("smp_linear") - shader:dx10color_write_enable(true, true, true, false) + --shader:dx10color_write_enable(true, true, true, false) --в ES отключено end diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/models_selflight.s b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/models_selflight.s index d0942623b9..6b075e7bd4 100644 --- a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/models_selflight.s +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/models_selflight.s @@ -2,18 +2,25 @@ function normal (shader, t_base, t_second, t_detail) shader:begin ("deffer_model_flat","deffer_base_flat") : fog (false) : emissive (true) - --shader:sampler ("s_base") :texture (t_base) +-- shader:sampler ("s_base") :texture (t_base) shader:dx10texture ("s_base", t_base) shader:dx10sampler ("smp_base") shader:dx10stencil ( true, cmp_func.always, 255 , 127, stencil_op.keep, stencil_op.replace, stencil_op.keep) shader:dx10stencil_ref (1) + + --shader: dx10color_write_enable( true, true, true, false) end function l_special (shader, t_base, t_second, t_detail) - shader:begin ("shadow_direct_model", "accum_emissive") + shader:begin ("deffer_model_flat", "accum_emissive") : zb (true,false) : fog (false) : emissive (true) + + shader:dx10texture ("s_base", t_base) + shader:dx10sampler ("smp_base") + + --shader: dx10color_write_enable( true, true, true, true) end diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/models_selflight_det.s b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/models_selflight_det.s index a669116e3a..c86de973b7 100644 --- a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/models_selflight_det.s +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/models_selflight_det.s @@ -9,13 +9,19 @@ function normal (shader, t_base, t_second, t_detail) 255 , 127, stencil_op.keep, stencil_op.replace, stencil_op.keep) shader:dx10stencil_ref (1) - shader: dx10color_write_enable( true, true, true, false) + + --shader: dx10color_write_enable( true, true, true, false) end function l_special (shader, t_base, t_second, t_detail) - shader:begin ("shadow_direct_model", "accum_emissivel") + shader:begin ("deffer_model_flat", "accum_emissivel") : zb (true,false) : fog (false) : emissive (true) - shader: dx10color_write_enable( true, true, true, false) + + shader:dx10texture ("s_base", t_base) + shader:dx10sampler ("smp_base") + + --shader: dx10color_write_enable( true, true, true, false) + --shader: dx10color_write_enable( true, true, true, true) end diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/models_selflightl.s b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/models_selflightl.s index 2c3b3edeab..81fef781b8 100644 --- a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/models_selflightl.s +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/models_selflightl.s @@ -9,11 +9,18 @@ function normal (shader, t_base, t_second, t_detail) 255 , 127, stencil_op.keep, stencil_op.replace, stencil_op.keep) shader:dx10stencil_ref (1) + + --shader: dx10color_write_enable( true, true, true, false) end function l_special (shader, t_base, t_second, t_detail) - shader:begin ("shadow_direct_model", "accum_emissivel") + shader:begin ("deffer_model_flat", "accum_emissivel") : zb (true,false) : fog (false) : emissive (true) + + shader:dx10texture ("s_base", t_base) + shader:dx10sampler ("smp_base") + + --shader: dx10color_write_enable( true, true, true, true) end diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/pbr_brdf.h b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/pbr_brdf.h new file mode 100644 index 0000000000..71409e3e4a --- /dev/null +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/pbr_brdf.h @@ -0,0 +1,293 @@ +/** + * @ Description: Enhanced Shaders and Color Grading 1.10 + * @ Author: https://www.moddb.com/members/kennshade + * @ Mod: https://www.moddb.com/mods/stalker-anomaly/addons/enhanced-shaders-and-color-grading-for-151 + */ + +//================================================================================================= +// Pseudo PBR shading for STALKER Anomaly +// Roughness is controlled with r2_gloss_min +//================================================================================================= +#include "pbr_settings.h" //load settings files +#define PI 3.14159265359 +//================================================================================================= +uniform float4 ssfx_lightsetup_1; // Spec intensity + +// Metalness +float calc_metalness(float4 alb_gloss, float material_ID) +{ + // material ID experiment + float metallerp = max(0.0, (material_ID * 4) - 0.5) / 4; // approx material + weight? //nowhere near + // metallerp = saturate((metallerp - 0.5) * 2); //metal threshold + // metallerp = saturate(((metallerp * 4) - 2) * 0.5); //metal threshold + + // binary metalness + float metalness = saturate(material_ID - 0.75 - 0.001) > 0 ? 1 : 0; + + // float metal_thres = METALNESS_THRESHOLD; + // float metal_soft = METALNESS_SOFTNESS; + + // float metal_thres = METALNESS_THRESHOLD * (1 - metallerp) * 2; + float metal_thres = pow(METALNESS_THRESHOLD, exp2(metallerp)); + float metal_soft = metal_thres * 0.9; + + // lerp on gloss + // metalness *= saturate(smoothstep(METALNESS_THRESHOLD-METALNESS_SOFTNESS, METALNESS_THRESHOLD+METALNESS_SOFTNESS, alb_gloss.a)); + metalness *= saturate((alb_gloss.a - (metal_thres - metal_soft)) / ((metal_thres + metal_soft) - (metal_thres - metal_soft))); + return metalness; +} + +float3 Soft_Light(float3 base, float3 blend) { return (blend <= 0.5) ? base - (1 - 2 * blend) * base * (1 - base) : base + (2 * blend - 1) * (sqrt(base) - base); } +//================================================================================================= +// Material +// +float3 calc_albedo_boost(float3 albedo) +{ + float3 blend = lerp(0.5, 1 - dot(albedo, LUMINANCE_VECTOR), ALBEDO_BOOST); // boost albedo by inv + return Soft_Light(albedo, blend); +} + +float3 calc_albedo(float4 alb_gloss, float material_ID) +{ + float metalness = calc_metalness(alb_gloss, material_ID); + + float3 albedo = alb_gloss.rgb; + // albedo = SRGBToLinear(albedo); + + albedo = calc_albedo_boost(albedo); + // albedo = SRGBToLinear(albedo); + + float3 screen_contrib = albedo; + screen_contrib = (1 - (1 - screen_contrib) * (1 - screen_contrib)) - lerp(dot(screen_contrib, LUMINANCE_VECTOR), screen_contrib, 0.5); + + albedo = SRGBToLinear(albedo); + screen_contrib = SRGBToLinear(screen_contrib); + + float3 albedo_metal = screen_contrib; // metal albedo is screen blend contrib, it gets rid of all highlights. + + return saturate(lerp(albedo, albedo_metal, metalness) * ALBEDO_AMOUNT); +} + +float3 calc_specular(float4 alb_gloss, float material_ID) +{ + float metalness = calc_metalness(alb_gloss, material_ID); + + float3 specular = float3(SPECULAR_BASE, SPECULAR_BASE, SPECULAR_BASE); // base fresnel to tweak + + float3 specular_metal = alb_gloss.rgb; // metal uses diffuse for specular + specular_metal = calc_albedo_boost(specular_metal); // boost albedo + specular_metal = SRGBToLinear(specular_metal); + + // tweaks for specular boost + // material_ID = sqrt(material_ID/0.75); + material_ID = saturate(material_ID * 1.425); + alb_gloss.a = sqrt(alb_gloss.a); + + /* + //old spec boost + float specular_boost = ((0.5+material_ID) * (0.5+alb_gloss.a))-0.25; //0.0 - 2.0 range + specular_boost = specular_boost - 1; //scale in -1 to +1 range + specular_boost = SPECULAR_RANGE * specular_boost; + specular_boost = max(0, specular_boost + 1); //0 - 2 + */ + + float specular_boost = (material_ID * 2 - 1) + (alb_gloss.a * 2 - 1); //-2.0 - +2.0 range + specular_boost = exp2(SPECULAR_RANGE * specular_boost); + specular_boost = pow(specular_boost, SPECULAR_POW); + + specular *= specular_boost; + + return saturate(lerp(specular, specular_metal, metalness)); +} + +float calc_rough(float4 alb_gloss, float material_ID) +{ + float metalness = calc_metalness(alb_gloss, material_ID); + + alb_gloss.a = pow(alb_gloss.a, ROUGHNESS_POW - (metalness * METAL_BOOST)); // metal boost + + float roughpow = 0.5 / max(0.001, 1 - Ldynamic_color.w); + float rough = pow(lerp(ROUGHNESS_HIGH, ROUGHNESS_LOW, alb_gloss.a), roughpow); + + // rough = pow(rough, 1 + (metalness * METAL_BOOST)); //metal boost + + return saturate(rough * rough); +} + +//================================================================================================= +// Rain and Foliage +// +void calc_rain(inout float3 albedo, inout float3 specular, inout float rough, in float4 alb_gloss, in float material_ID, in float rainmask) +{ + // rain based on Remember Me's implementation + // float wetness = saturate(rain_params.x*rainmask); + float wetness = saturate(smoothstep(0.1, 0.9, rain_params.x * rainmask)); + + float porosity = 1 - saturate(material_ID * 1.425); // metal material at 0, concrete at 1 + // porosity = saturate((porosity-0.5)/0.4); //Remember Me rain porosity + + float factor = lerp(1, 0.2, porosity); // albedo darkening factor + + albedo *= lerp(1, factor, wetness); + rough = lerp(0.001, rough, lerp(1, factor, wetness)); + specular = lerp(specular, 0.02, wetness); +} + +void calc_foliage(inout float3 albedo, inout float3 specular, inout float rough, in float4 alb_gloss, in float mat_id) +{ + // specular = (abs(mat_id-MAT_FLORA) <= MAT_FLORA_ELIPSON) ? calc_specular(alb_gloss, 0.0) : specular; + // specular = (abs(mat_id-MAT_FLORA) <= MAT_FLORA_ELIPSON) ? alb_gloss.g * 0.02 : specular; + // specular = (abs(mat_id-MAT_FLORA) <= MAT_FLORA_ELIPSON) ? pow(alb_gloss.g * 0.1414, 2) : specular; + + if (abs(mat_id - MAT_FLORA) <= MAT_FLORA_ELIPSON) + { + // float light = 1.0f - saturate(dot(L_hemi_color.rgb, float3(1,1,1))); + specular = alb_gloss.g * 0.05f; // max( light * 0.025f, 0.008f); + } +} + +//================================================================================================= +// Functions +// + +float F_Shlick(float f0, float f90, float vDotH) { return lerp(f0, f90, pow(1 - vDotH, 5)); } + +float3 F_Shlick(float3 f0, float3 f90, float vDotH) { return lerp(f0, f90, pow(1 - vDotH, 5)); } +// We have a better approximation of the off specular peak +// but due to the other approximations we found this one performs better . +// N is the normal direction +// R is the mirror vector +// This approximation works fine for G smith correlated and uncorrelated +float3 getSpecularDominantDir(float3 N, float3 R, float roughness) +{ + float smoothness = saturate(1 - roughness); + float lerpFactor = smoothness * (sqrt(smoothness) + roughness); + // The result is not normalized as we fetch in a cubemap + return lerp(N, R, lerpFactor); +} + +//================================================================================================= +// Shading +// + +// include BRDFs +#include "pbr_brdf_blinn.h" //brdf +#include "pbr_brdf_ggx.h" //brdf + +float Lit_Burley(float nDotL, float nDotV, float vDotH, float rough) +{ + float fd90 = 0.5 + 2 * vDotH * vDotH * rough; + float lightScatter = F_Shlick(1, fd90, nDotL); + float viewScatter = F_Shlick(1, fd90, nDotV); + return (lightScatter * viewScatter) / PI; +} + +float Lambert_Source(float nDotL, float rough) +{ + float exponent = lerp(1.4, 0.6, rough); + return (pow(nDotL, exponent) * ((exponent + 1.0) * 0.5)) / max(1e-5, PI * nDotL); +} + +float Lit_Diffuse(float nDotL, float nDotV, float vDotH, float rough) +{ +#ifdef USE_BURLEY_DIFFUSE + return Lit_Burley(nDotL, nDotV, vDotH, rough); +#else + return Lambert_Source(nDotL, rough); +#endif +} + +float3 Lit_Specular(float nDotL, float nDotH, float nDotV, float vDotH, float3 f0, float rough) +{ +#ifdef USE_GGX_SPECULAR + return Lit_GGX(nDotL, nDotH, nDotV, vDotH, f0, rough); // GGX is much more expensive but looks nicer +#else + return Lit_Blinn(nDotL, nDotH, nDotV, vDotH, f0, rough); // much cheaper pbr blinn +#endif +} + +float3 Lit_BRDF(float rough, float3 albedo, float3 f0, float3 V, float3 N, float3 L) +{ + // SPECULAR ADJUSTMENTS - SSS Update 18 + // Color, intensity and some minor adjustments. + // https://www.moddb.com/mods/stalker-anomaly/addons/screen-space-shaders/ + + float3 H = normalize(V + L); + + float DotNV = dot(N, V); + + float nDotL = saturate(dot(N, L)); + float nDotH = saturate(dot(N, H)); + float nDotV = max(1e-5, DotNV); + float vDotH = saturate(dot(V, H)); + + float3 diffuse_term = Lit_Diffuse(nDotL, nDotV, vDotH, rough).rrr; + diffuse_term *= albedo; + + // Specular + float3 specular_term = Lit_Specular(nDotL, nDotH, nDotV, vDotH, f0, rough); + + // Horizon falloff + float horizon = saturate(DotNV * 2.0f); + specular_term *= horizon * horizon; + + // Specular color + float3 light = saturate(Ldynamic_color.rgb); + specular_term *= 1.0f - ((light.r + light.g + light.b) / 3.0) * (1.0f - ssfx_lightsetup_1.x); + specular_term *= lerp(1.0f, Ldynamic_color.rgb, ssfx_lightsetup_1.y); + + return (diffuse_term + specular_term) * nDotL * PI; +} + +//================================================================================================= +// Ambient +// + +float EnvBurley(float roughness, float NV) +{ + // Burley (Hill's curve) + float d0 = 0.97619 - 0.488095 * pow(1.0 - NV, 5.0); + float d1 = 1.55754 + (-2.02221 + (2.56283 - 1.06244 * NV) * NV) * NV; + return lerp(d0, d1, roughness); +} + +float Amb_Diffuse(float3 f0, float rough, float nDotV) +{ +#ifdef USE_BURLEY_DIFFUSE + return EnvBurley(rough, nDotV); +#else + return 1.0; +#endif +} + +float3 Amb_Specular(float3 f0, float rough, float nDotV) +{ +#ifdef USE_GGX_SPECULAR + return EnvGGX(f0, rough, nDotV); +#else + return EnvBlops2(f0, rough, nDotV); +#endif +} + +float3 Amb_BRDF(float rough, float3 albedo, float3 f0, float3 env_d, float3 env_s, float3 V, float3 N) +{ + float DotNV = dot(N, V); + // float nDotV = 1e-5 + abs(dot(N, V)); //DICE + float nDotV = max(1e-5, DotNV); + + float3 diffuse_term = Amb_Diffuse(f0, rough, nDotV); + diffuse_term *= env_d * albedo; + + float3 specular_term = Amb_Specular(f0, rough, nDotV); + specular_term *= env_s; + + // horizon occlusion with falloff, should be computed for direct specular too + // float R = reflect(V, N); + // float horizon = saturate(1.0 + dot(R, N)); //needs vertex normals + float horizon = saturate(DotNV * 2.0f); // 0.95 + horizon *= horizon; + + specular_term *= horizon; // horizon atten + + return diffuse_term + specular_term; +} \ No newline at end of file diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/pbr_brdf_blinn.h b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/pbr_brdf_blinn.h new file mode 100644 index 0000000000..35349e3cd1 --- /dev/null +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/pbr_brdf_blinn.h @@ -0,0 +1,61 @@ +// BLOPS 2 blinn phong PBR +// credit to Treyarch + +float CalcGlossmap(float rough) { return 1.0 - rough; } + +float RoughToGlossExp(float rough) +{ + // return = 2 / ((rough*rough) - 2); UE4 blinn + return pow(8192, CalcGlossmap(rough)); // blops2 + // return pow(2, 11 * CalcGlossmap(rough)) - 1; +} + +float D_Blinn(float a, float nDotH) +{ + return pow(nDotH, a) * ((a + 2) / (8 * PI)); // BLOPS2 +} + +float G_Smith(float a, float nDotX) +{ + float k = 2 / sqrt(PI * (a + 2)); // remapping for BLOPS + return nDotX / (nDotX * (1 - k) + k); +} + +float G_SmithBLOPS(float a, float nDotl, float nDotv) +{ + float k = 2 / sqrt(PI * (a + 2)); // remapping for BLOPS + float A = nDotl * (1 - k) + k; // remapping for BLOPS + float B = nDotv * (1 - k) + k; // remapping for BLOPS + + return 1 / (A * B); +} + +float3 Lit_Blinn(float nDotL, float nDotH, float nDotV, float vDotH, float3 f0, float rough) +{ + float a = RoughToGlossExp(rough); + + float d = D_Blinn(a, nDotH); + + // float v = G_Smith(a, nDotL) * G_Smith(a, nDotV); + float v = G_SmithBLOPS(a, nDotL, nDotV); + + float3 f90Atten = saturate(50 * f0); // UE4 specular shadowing + float3 f = F_Shlick(f0, f90Atten, vDotH); + + return d * f * v; +} + +float3 EnvBlops2(float3 f0, float rough, float NoV) +{ + float g = CalcGlossmap(rough); + float3 f90Atten = saturate(50 * f0); // UE4 specular shadowing + + float4 t = float4(1 / 0.96, 0.475, (0.0275 - 0.25 * 0.04) / 0.96, 0.25); + t *= float4(g, g, g, g); + t += float4(0, 0, (0.015 - 0.75 * 0.04) / 0.96, 0.75); + + float a0 = t.x * min(t.y, exp2(-9.28 * NoV)) + t.z; + float a1 = t.w; + + return saturate(f90Atten * a0 + f0 * (a1 - a0)); +} \ No newline at end of file diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/pbr_brdf_ggx.h b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/pbr_brdf_ggx.h new file mode 100644 index 0000000000..4ef624a1b6 --- /dev/null +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/pbr_brdf_ggx.h @@ -0,0 +1,119 @@ +float D_GGX(float NdotH, float a2) +{ + float denominator = (NdotH * a2 - NdotH) * NdotH + 1.0; + return a2 / (PI * denominator * denominator); +} + +float Lambda_Smith(float NdotX, float a) +{ + float a2 = a * a; + float NdotX_2 = NdotX * NdotX; + return (-1.0 + sqrt(a2 * (1.0 - NdotX_2) / NdotX_2 + 1.0)) * 0.5; +} + +// Height Correlated Masking-shadowing function +float G2_Smith_Correlated(float NdotL, float NdotV, float a) +{ + float lambdaV = Lambda_Smith(NdotV, a); + float lambdaL = Lambda_Smith(NdotL, a); + + return 1.0 / (1.0 + lambdaV + lambdaL); +} + +float G2_SmithJointApprox(float NdotL, float NdotV, float a) +{ + float Vis_V = NdotL * (NdotV * (1 - a) + a); + float Vis_L = NdotV * (NdotL * (1 - a) + a); + return 0.5 * rcp(Vis_V + Vis_L); +} + +float3 Lit_GGX(float NdotL, float NdotH, float NdotV, float VdotH, float3 F0, float rough) +{ + // Alpha + float a = rough * rough; + float a2 = a * a; + + // Normal distribution function + float D = D_GGX(NdotH, a2); + + // Masking-shadowing + // float V = G2_Smith_Correlated(NdotL, NdotV, a); + float V = G2_SmithJointApprox(NdotL, NdotV, a); // denom included? + + // Fresnel + float3 f90Atten = saturate(50 * F0); // UE4 specular shadowing + float3 F = F_Shlick(F0, f90Atten, VdotH); + + // Numerator + float3 numerator = (D * V) * F; + + // Denominator + // float denominator = 4.0 * NdotV; + + return numerator; // UE4 has no denom + // return numerator / denominator; +} + +// UE4 mobile approx +float2 EnvBRDFApprox(float Roughness, float NoV) +{ + const float4 c0 = {-1, -0.0275, -0.572, 0.022}; + const float4 c1 = {1, 0.0425, 1.04, -0.04}; + float4 r = Roughness * c0 + c1; + float a004 = min(r.x * r.x, exp2(-9.28 * NoV)) * r.x + r.y; + float2 AB = float2(-1.04, 1.04) * a004 + r.zw; + return AB; +} + +//------------------------------------------------------------------------------------------------- +// Returns scale and bias values for environment specular reflections that represents the +// integral of the geometry/visibility + fresnel terms for a GGX BRDF given a particular +// viewing angle and roughness value. The final value is computed using polynomials that were +// fitted to tabulated data generated via monte carlo integration. +//------------------------------------------------------------------------------------------------- +float2 GGXEnvironmentBRDFScaleBias(float roughness, float nDotV) +{ + const float sqrtRoughness = sqrt(roughness); + const float nDotV2 = nDotV * nDotV; + const float sqrtRoughness2 = sqrtRoughness * sqrtRoughness; + const float sqrtRoughness3 = sqrtRoughness2 * sqrtRoughness; + + const float delta = 0.991086418474895f + (0.412367709802119f * sqrtRoughness * nDotV2) - (0.363848256078895f * sqrtRoughness2) - (0.758634385642633f * nDotV * sqrtRoughness2); + const float bias = saturate((0.0306613448029984f * sqrtRoughness) + 0.0238299731830387f / (0.0272458171384516f + sqrtRoughness3 + nDotV2) - 0.0454747751719356f); + + const float scale = saturate(delta - bias); + return float2(scale, bias); +} + +// LVutner ambient BRDF +float2 integrate_brdf(float roughness, float NV) +{ + // Schlick's approximation + float F_partial = pow(1.0 - NV, 5.0); + + // GGX + const float4 c0 = float4(-1.0, -0.0275, -0.26, 0.0109); + const float4 c1 = float4(1.0, 0.0455, 1.0417, -0.0417); + + float4 r = roughness * c0 + c1; + float a004 = min(0.9 - 0.75 * roughness, F_partial) * r.x + r.y; + float2 AB = float2(-1.0417, 1.0417) * a004 + r.zw; + + // Output (Scale, Bias, Burley) + return float2(AB.x, AB.y); +} + +float3 EnvGGX(float3 f0, float rough, float nDotV) +{ + // UE4 GGX + float3 f90Atten = saturate(50 * f0); // UE4 specular shadowing + float2 AB = EnvBRDFApprox(rough, nDotV); + + // Matt Pettineo GGX + // float2 AB = GGXEnvironmentBRDFScaleBias(rough, nDotV); + + // LVutner GGX + // float2 AB = integrate_brdf(rough, nDotV); + + return (f0 * AB.x + AB.y * f90Atten); +} \ No newline at end of file diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/pbr_cubemap_check.h b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/pbr_cubemap_check.h new file mode 100644 index 0000000000..b3d485283b --- /dev/null +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/pbr_cubemap_check.h @@ -0,0 +1,2 @@ +// No PBR Cubemaps +//#define USE_PBR_CUBEMAPS \ No newline at end of file diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/pbr_settings.h b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/pbr_settings.h new file mode 100644 index 0000000000..d8ad3bfd78 --- /dev/null +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/pbr_settings.h @@ -0,0 +1,26 @@ +/** + * @ Description: Enhanced Shaders and Color Grading 1.10 + * @ Author: https://www.moddb.com/members/kennshade + * @ Mod: https://www.moddb.com/mods/stalker-anomaly/addons/enhanced-shaders-and-color-grading-for-151 + */ + +//================================================================================================= +// Settings for PBR conversion +//================================================================================================= +#define USE_BURLEY_DIFFUSE // use expensive Disney/Burley diffuse +#define USE_GGX_SPECULAR // use more expensive GGX specular +//================================================================================================= +#define ALBEDO_BOOST 0.0 +#define ALBEDO_AMOUNT 1.00 + +#define ROUGHNESS_LOW 0.5 +#define ROUGHNESS_HIGH 1.0 +#define ROUGHNESS_POW 1.0 + +#define SPECULAR_BASE 0.01 +#define SPECULAR_RANGE 1.0 +#define SPECULAR_POW 1.0 + +#define METAL_BOOST 0.25 +#define METALNESS_THRESHOLD 0.125 +#define METALNESS_SOFTNESS 0.125 \ No newline at end of file diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/pnv.h b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/pnv.h index 10ab152031..94dc220d8a 100644 --- a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/pnv.h +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/pnv.h @@ -21,7 +21,7 @@ float4 calc_night_vision_effect(float2 tc0, float4 color, float3 NV_COLOR) { - float lum = dot(color.rgb, float3(0.3f, 0.38f, 0.22f) * NV_BRIGHTNESS); // instead of float3 use LUMINANCE_floatTOR in stalker + float lum = dot(color.rgb, LUMINANCE_VECTOR * NV_BRIGHTNESS); // instead of float3 use LUMINANCE_floatTOR in stalker color.rgb = NV_COLOR * lum; // cheap noise function diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/rain_apply_gloss.ps b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/rain_apply_gloss.ps index 24f50c6840..7d1bea1a6c 100644 Binary files a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/rain_apply_gloss.ps and b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/rain_apply_gloss.ps differ diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/rain_patch_normal.ps b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/rain_patch_normal.ps index 1b18f217e3..456193a53f 100644 Binary files a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/rain_patch_normal.ps and b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/rain_patch_normal.ps differ diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/screenspace_common_ripples.h b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/screenspace_common_ripples.h index acc5db618e..736c328f17 100644 --- a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/screenspace_common_ripples.h +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/screenspace_common_ripples.h @@ -1,43 +1,61 @@ /** - * @ Version: SCREEN SPACE SHADERS - UPDATE 12 + * @ Version: SCREEN SPACE SHADERS - UPDATE 18 * @ Description: Ripples code - * @ Modified time: 2022-10-29 05:05 + * @ Modified time: 2023-09-21 01:31 * @ Author: https://www.moddb.com/members/ascii1457 * @ Mod: https://www.moddb.com/mods/stalker-anomaly/addons/screen-space-shaders + * + * Based on the work of Sébastien Lagarde for the game "Remember Me" + * https://seblagarde.wordpress.com/2013/01/03/water-drop-2b-dynamic-rain-and-its-effects/ + * + * Setup : [ x: speed | y: intensity | z: ripple frequency ] + * Sample : [ x: Fade | y: Normal-Y | z: Normal-X | w: Time Offset ] */ -static const float4 SSFX_ripples_timemul = float4(1.0f, 0.85f, 0.93f, 1.13f); -static const float4 SSFX_ripples_timeadd = float4(0.0f, 0.2f, 0.45f, 0.7f); +static const float3 SSFX_ripples_speed = float3(1.05f, 1.31f, 1.58f); +static const float4 SSFX_ripples_offset = float4(0.5f, 0.25f, 0.31f, 0.5f); -// https://seblagarde.wordpress.com/2013/01/03/water-drop-2b-dynamic-rain-and-its-effects/ -float3 SSFX_computeripple(float4 Ripple, float CurrentTime, float Weight) +static const float SSFX_ripples_PI = 3.141592f; + +float2 ssfx_process_ripples(float4 ripples, float3 setup) { - Ripple.yz = Ripple.yz * 2 - 1; // Decompress perturbation + // Get bump from texture and transform to -1.0 ~ 1.0 + float2 ripples_N = ripples.yz * 2.0 - 1.0; + + // Apply time + float RFrac = frac(ripples.w + timers.x * setup.x); // Apply time shift + float TimeFrac = RFrac - 1.0f + ripples.x; // Fade + float RFreq = clamp(TimeFrac * setup.z, 0.0f, 4.0); // Frequency and limit ( 2 = 1 full ripple ) + float FinalFactor = saturate(0.7f - RFrac) * ripples.x * sin(RFreq * SSFX_ripples_PI); // Create ripples - float DropFrac = frac(Ripple.w + CurrentTime); // Apply time shift - float TimeFrac = DropFrac - 1.0f + Ripple.x; - float DropFactor = saturate(0.2f + Weight * 0.8f - DropFrac); - float FinalFactor = DropFactor * Ripple.x * sin(clamp(TimeFrac * 9.0f, 0.0f, 3.0f) * 3.14159265359f); + // Fade + FinalFactor *= smoothstep(4.0f, 0, RFreq); - return float3(Ripple.yz * FinalFactor * 0.65f, 1.0f); + // Apply intensity + ripples_N *= FinalFactor * setup.y; + + return ripples_N; } -float3 SSFX_ripples(Texture2D ripple_tex, float2 tc) +float2 ssfx_rain_ripples(Texture2D ripples_tex, float2 uvs, float3 setup, float depth) { - float4 Times = (timers.x * SSFX_ripples_timemul + SSFX_ripples_timeadd) * 1.5f; - Times = frac(Times); + // Falloff + float Dist = 15.0f - depth; + + // Discard when depth > 15 + if (Dist < 0) + return 0; - float4 Weights = float4(0, 1.0, 0.65, 0.25); + // Sample layers + float4 Layer0 = ripples_tex.Sample(smp_linear, uvs); + float4 Layer1 = ripples_tex.Sample(smp_linear, uvs * 0.61f + SSFX_ripples_offset.xy); + float4 Layer2 = ripples_tex.Sample(smp_linear, uvs * 0.87f + SSFX_ripples_offset.zw); - // Compute ripples - float3 Ripple1 = SSFX_computeripple(ripple_tex.Sample(smp_base, tc + float2(0.25f, 0.0f)), Times.x, Weights.x); - float3 Ripple2 = SSFX_computeripple(ripple_tex.Sample(smp_base, tc + float2(-0.55f, 0.3f)), Times.y, Weights.y); - float3 Ripple3 = SSFX_computeripple(ripple_tex.Sample(smp_base, tc + float2(0.6f, 0.85f)), Times.z, Weights.z); - float3 Ripple4 = SSFX_computeripple(ripple_tex.Sample(smp_base, tc + float2(0.5f, -0.75f)), Times.w, Weights.w); + // Process 3 layers of ripples + float2 result = ssfx_process_ripples(Layer0, float3(SSFX_ripples_speed.x * setup.x, setup.yz)) + + ssfx_process_ripples(Layer1, float3(SSFX_ripples_speed.y * setup.x, setup.yz)) + ssfx_process_ripples(Layer2, float3(SSFX_ripples_speed.z * setup.x, setup.yz)); - Weights = saturate(Weights * 4); - float4 Z = lerp(1, float4(Ripple1.z, Ripple2.z, Ripple3.z, Ripple4.z), Weights); - float3 Normal = float3(Weights.x * Ripple1.xy + Weights.y * Ripple2.xy + Weights.z * Ripple3.xy + Weights.w * Ripple4.xy, Z.x * Z.y * Z.z * Z.w); + result *= Dist * 0.0666f; // 0.0 ~ 15.0 To 0.0 ~ 1.0 - return normalize(Normal) * 0.5 + 0.5; + return clamp(result, -1.0f, 1.0f); } \ No newline at end of file diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/screenspace_fog.h b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/screenspace_fog.h index 4889f360a3..5c938cd7b5 100644 --- a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/screenspace_fog.h +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/screenspace_fog.h @@ -32,7 +32,7 @@ float SSFX_HEIGHT_FOG(float3 P, float World_Py, inout float3 color) float3 FOG_COLOR = lerp(fog_color, Sun, FogBlend); // Apply fog to color - color = lerp(color, FOG_COLOR * 2.0f / 3.0f, fogresult); + color = lerp(color, FOG_COLOR, fogresult); // Return distance fog. return fog; diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/screenspace_reflections.h b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/screenspace_reflections.h index 956669b65e..48e98795a9 100644 --- a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/screenspace_reflections.h +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/screenspace_reflections.h @@ -1,7 +1,7 @@ /** - * @ Version: SCREEN SPACE SHADERS - UPDATE 14.3 + * @ Version: SCREEN SPACE SHADERS - UPDATE 18 * @ Description: SSR implementation - * @ Modified time: 2023-01-29 08:40 + * @ Modified time: 2023-09-29 06:42 * @ Author: https://www.moddb.com/members/ascii1457 * @ Mod: https://www.moddb.com/mods/stalker-anomaly/addons/screen-space-shaders */ @@ -9,7 +9,7 @@ #include "screenspace_common.h" #include "settings_screenspace_SSR.h" -uniform float4 rain_params; +uniform float4 ssfx_is_underground; static const int2 q_ssr_steps[6] = { @@ -163,9 +163,9 @@ void SSFX_ScreenSpaceReflections(float2 tc, float4 P, float3 N, float gloss, ino // Sky is the reflection base... #ifdef G_SSR_CHEAP_SKYBOX - reflection = SSFX_calc_env(v2reflect) * G_SSR_SKY_INTENSITY; + reflection = SSFX_calc_env(v2reflect) * G_SSR_SKY_INTENSITY * !ssfx_is_underground.x; #else - reflection = SSFX_calc_sky(v2reflect) * G_SSR_SKY_INTENSITY; + reflection = SSFX_calc_sky(v2reflect) * G_SSR_SKY_INTENSITY * !ssfx_is_underground.x; #endif // Valid UV coor? SSFX_trace_ssr_ray return 0.0f if uv is out of bounds or sky. diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/screenspace_wind.h b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/screenspace_wind.h new file mode 100644 index 0000000000..0e8856bfd9 --- /dev/null +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/screenspace_wind.h @@ -0,0 +1,163 @@ +/** + * @ Version: SCREEN SPACE SHADERS - UPDATE 19 + * @ Description: Wind Main File + * @ Modified time: 2023-11-23 21:02 + * @ Author: https://www.moddb.com/members/ascii1457 + * @ Mod: https://www.moddb.com/mods/stalker-anomaly/addons/screen-space-shaders + */ + +// wind_direction wind_velocity E.m_fTreeAmplitudeIntensity +uniform float4 wind_params; + +uniform float4 ssfx_wind; // DBG: X: Wind intensity - Y: North Dir - Z: South Dir +uniform float4 ssfx_wind_gust; // X: Intensity +uniform float4 ssfx_wind_anim; + +uniform float is_bugged_flora; + +Texture2D s_waves; +sampler smp_linear2; + +struct wind_setup +{ + float2 direction; + float speed; + float sqrt_speed; + + float trees_animspeed; + float trees_trunk_animspeed; + float trees_bend; + + float grass_animspeed; + float grass_turbulence; + float grass_push; + float grass_wave; +}; + +wind_setup ssfx_wind_setup() +{ + // wind : [x:time] [y:TreeAmplitudeIntensity] [z:gust] [w:ExtraPerlin] + wind_setup wsetup; + + // Direction, speed and wind gust. + wsetup.direction = normalize(ssfx_wind.yz); + + if (ssfx_wind.y == 0 && ssfx_wind.z == 0) + { + // Radians to Vector + float r = -wind_params.x + 1.57079f; + wsetup.direction = float2(cos(r), sin(r)); + } + + wsetup.speed = saturate(ssfx_wind.x); + + if (wsetup.speed <= 0) + wsetup.speed = saturate(wind_params.y * 0.001); + + wsetup.sqrt_speed = saturate(sqrt(wsetup.speed * 1.66f)); + + wsetup.trees_animspeed = 11.0f; + wsetup.trees_trunk_animspeed = 0.15f; + wsetup.trees_bend = 0.5f; + + wsetup.grass_animspeed = 10.0; + wsetup.grass_turbulence = 1.5f; + wsetup.grass_push = 1.5f; + wsetup.grass_wave = 0.2f; + + return wsetup; +} + +#ifdef SSFX_WIND_ISGRASS + +// Flow Map - X: X-Anim | Y: Z-Anim | Z: Wind Wave | W : Detail + +float3 ssfx_wind_grass(float3 pos, float H, wind_setup W) +{ + // Height Limit. ( Add stiffness to tall grass ) + float HLimit = saturate(H * H - 0.01f) * saturate(1.0f - H * 0.1f); + + // Offset animation + float2 Offset = -ssfx_wind_anim.xy * W.grass_animspeed; + + // Sample ( The scale defines the detail of the motion ) + float3 Flow = s_waves.SampleLevel(smp_linear2, (pos.xz + Offset) * 0.018f, 0) * W.sqrt_speed; + + // Grass Motion ( -1.0 ~ 1.0 ). Turbulence. + float2 GrassMotion = (Flow.xy * 2.0f - 1.0f) * W.sqrt_speed * W.grass_turbulence; + + // Apply wind direction and flow. Wind push. + float2 WindDir = Flow.z * W.sqrt_speed * W.direction * W.grass_push; + + // Add everything and apply height limit + float3 Final = float3(GrassMotion.x + WindDir.x, Flow.z * W.grass_wave, GrassMotion.y + WindDir.y) * HLimit; + + return Final; +} + +#else // Non Grass + +float3 ssfx_wind_tree_trunk(float3 pos, float Tree_H, wind_setup W) +{ + // Phase ( from matrix ) + Offset + float Phase = m_xform._24 + ssfx_wind_anim.z * W.trees_trunk_animspeed; + + // Trunk wave + float TWave = (cos(Phase) * sin(Phase * 5.0f) + 0.5f) * ssfx_wind_gust.x * W.trees_bend; + + float WSpeed = saturate(W.sqrt_speed * 1.5f); + + // Base wind speed displacement + float Base_Bend = WSpeed * 0.007f * saturate(1.0f - Tree_H * 0.005f); + + // Intensity ( Squared height ) + Base_Bend *= Tree_H * Tree_H * TWave * WSpeed; + + // Apply direction + float2 Final = Base_Bend.xx * W.direction; + + return float3(Final, saturate((TWave + 1.0f) * 0.5)); +} + +float3 ssfx_wind_tree_branches(float3 pos, float Tree_H, float tc_y, wind_setup W) +{ + // UV Offset + float2 Offset = -ssfx_wind_anim.xy * W.trees_animspeed; + + // Sample flow map + float3 Flow = s_waves.SampleLevel(smp_linear2, (pos.xz + Offset) * 0.02f, 0); + + // Sample 2, slower and detailed + float3 Flow2 = s_waves.SampleLevel(smp_linear2, (pos.xz + Offset * 0.2f) * 0.1f, 0); + + // Branch motion [ -1.0 ~ 1.0 ] + float3 branchMotion = 0; + + // Base Motion + if (!is_bugged_flora) + branchMotion.xyz = float3(Flow.x, Flow2.y, Flow.y) * 2.0f - 1.0f; + + // Trunk position + float3 Trunk = ssfx_wind_tree_trunk(pos, Tree_H, W); + + // Gust from trunk data. + branchMotion.xz *= Trunk.z * clamp(Tree_H * 0.1f, 1.0f, 2.5f); + + // Add wind direction + if (!is_bugged_flora) + branchMotion.xz += Flow2.z * W.direction; + + // Add wind gust + branchMotion.y *= saturate(Tree_H * 0.1f); + + // Everything is limited by the UV and wind speed + if (!is_bugged_flora) + branchMotion *= (1.0f - tc_y) * W.speed; + + // Add trunk animation + branchMotion.xz += Trunk.xy; + + return branchMotion; +} + +#endif \ No newline at end of file diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/settings_screenspace_FLORA.h b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/settings_screenspace_FLORA.h index 71134c0388..d8d4cbc8f0 100644 --- a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/settings_screenspace_FLORA.h +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/settings_screenspace_FLORA.h @@ -1,5 +1,9 @@ // [ SETTINGS ] [ FLORA FIXES ] -#define G_TREES_SPECULAR 1.0f // Trees specular intensity -#define G_GRASS_SPECULAR 1.0f // Grass specular intensity -#define G_SSS_INTENSITY 0.5f // Subsurface Scattering intensity +#ifndef settings_screenspace_FLORA +#define settings_screenspace_FLORA + +uniform float4 ssfx_florafixes_1; +uniform float4 ssfx_florafixes_2; + +#endif diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/settings_screenspace_SSR.h b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/settings_screenspace_SSR.h index 5f5a721f3d..2c7d5dd2bf 100644 --- a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/settings_screenspace_SSR.h +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/settings_screenspace_SSR.h @@ -7,7 +7,7 @@ #define G_SSR_INTENSITY 1.3f // Global reflection intensity ( 1.0f = 100% ~ 0.0f = 0% ) #define G_SSR_MAX_INTENSITY 0.5f // Global reflection MAX intensity. #define G_SSR_SKY_INTENSITY 0.6f // Sky reflection intensity ( 1.0f = 100% ~ 0.0f = 0% ) -#define G_SSR_FLORA_INTENSITY 0.5f // Adjust grass and tree branches intensity +#define G_SSR_FLORA_INTENSITY 0.2f // Adjust grass and tree branches intensity #define G_SSR_TERRAIN_BUMP_INTENSITY 0.6f // Terrain bump intensity ( Lower values will generate cleaner reflections ) #define G_SSR_WEAPON_INTENSITY 0.5f // Weapons & arms reflection intensity. ( 1.0f = 100% ~ 0.0f = 0% ) diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/settings_screenspace_WATER.h b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/settings_screenspace_WATER.h index 6e6a2e27bb..9e51e8c194 100644 --- a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/settings_screenspace_WATER.h +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/settings_screenspace_WATER.h @@ -14,7 +14,7 @@ #define G_SSR_WATER_FOG_MAXDEPTH 2.0f // Maximum visibility underwater. -#define G_SSR_WATER_RAIN 0.4f // Max intensity of rain drops +#define G_SSR_WATER_RAIN 1.25f // Intensity of rain ripples #define G_SSR_WATER_SPECULAR 6.0f // Sun/Moon specular intensity #define G_SSR_WATER_SPECULAR_NORMAL 0.2f // Specular normal intensity. ( You may need to adjust this if you change the value of G_SSR_WATER_WAVES ) diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/shadow.h b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/shadow.h index 54487e4484..45fd7bcfcf 100644 --- a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/shadow.h +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/shadow.h @@ -16,10 +16,6 @@ sampler smp_jitter; Texture2D jitter0; Texture2D jitter1; -// uniform sampler2D jitter2; -// uniform sampler2D jitter3; -// uniform float4 jitterS; - Texture2D jitterMipped; #ifndef USE_ULTRA_SHADOWS @@ -28,6 +24,11 @@ Texture2D jitterMipped; #define KERNEL 1.0f #endif +#define PCSS_PIXEL int(4) +#define PCSS_STEP int(2) +#define PCSS_PIXEL_MIN float(1.0) +#define PCSS_SUN_WIDTH float(150.0) + float modify_light(float light) { return (light > 0.7 ? 1.0 : lerp(0.0, 1.0, saturate(light / 0.7))); } ////////////////////////////////////////////////////////////////////////////////////////// @@ -43,8 +44,6 @@ float sample_hw_pcf(float4 tc, float4 shift) return s_smap.SampleCmpLevelZero(smp_smap, tc.xy, tc.z).x; } -#define GS2 3 - float shadow_hw(float4 tc) { float s0 = sample_hw_pcf(tc, float4(-1, -1, 0, 0)); @@ -55,452 +54,6 @@ float shadow_hw(float4 tc) return (s0 + s1 + s2 + s3) / 4.h; } -#if SUN_QUALITY >= 4 -#define FILTER_SIZE 11 -#define FS FILTER_SIZE -#define FS2 (FILTER_SIZE / 2) - -static const float W2[11][11] = { - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.0}, {0.0, 0.2, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.2, 0.0}, - {0.0, 0.2, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.2, 0.0}, {0.0, 0.2, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.2, 0.0}, {0.0, 0.2, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.2, 0.0}, - {0.0, 0.2, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.2, 0.0}, {0.0, 0.2, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.2, 0.0}, {0.0, 0.2, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.2, 0.0}, - {0.0, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, -}; - -static const float W1[11][11] = { - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.0, 0.0}, - {0.0, 0.0, 0.2, 1.0, 1.0, 1.0, 1.0, 1.0, 0.2, 0.0, 0.0}, {0.0, 0.0, 0.2, 1.0, 1.0, 1.0, 1.0, 1.0, 0.2, 0.0, 0.0}, {0.0, 0.0, 0.2, 1.0, 1.0, 1.0, 1.0, 1.0, 0.2, 0.0, 0.0}, - {0.0, 0.0, 0.2, 1.0, 1.0, 1.0, 1.0, 1.0, 0.2, 0.0, 0.0}, {0.0, 0.0, 0.2, 1.0, 1.0, 1.0, 1.0, 1.0, 0.2, 0.0, 0.0}, {0.0, 0.0, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.0, 0.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, -}; - -static const float W0[11][11] = { - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.1, 0.1, 0.1, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.1, 1.0, 0.1, 0.0, 0.0, 0.0, 0.0}, - {0.0, 0.0, 0.0, 0.0, 0.1, 0.1, 0.1, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, -}; - -float Fw(int r, int c, float fL) -{ - return (1.0 - fL) * (1.0 - fL) * (1.0 - fL) * W0[r][c] + 3.0f * (1.0 - fL) * (1.0 - fL) * fL * W1[r][c] + 3.0f * fL * fL * (1.0 - fL) * W2[r][c] + fL * fL * fL * 1.0f; -} - -#define BLOCKER_FILTER_SIZE 11 -#define BFS BLOCKER_FILTER_SIZE -#define BFS2 (BLOCKER_FILTER_SIZE / 2) - -#define SUN_WIDTH 300.0f - -// uses gather for DX11/10.1 and visibilty encoding for DX10.0 -float shadow_extreme_quality(float3 tc) -{ - float s = 0.0f; - float2 stc = (SMAP_size * tc.xy) + float2(0.5, 0.5); - float2 tcs = floor(stc); - float2 fc; - int row; - int col; - float w = 0.0; - float avgBlockerDepth = 0; - float blockerCount = 0; - float fRatio; - float4 v1[FS2 + 1]; - float2 v0[FS2 + 1]; - float2 off; - - fc = stc - tcs; - tc.xy = tc.xy - ((1.0f / SMAP_size) * fc); - tc.z -= 0.0001f; - -#if defined(SM_4_1) || defined(SM_5) - // find number of blockers and sum up blocker depth - for (row = -BFS2; row <= BFS2; row += 2) - { - for (col = -BFS2; col <= BFS2; col += 2) - { - float4 d4 = s_smap.Gather(smp_nofilter, tc.xy, int2(col, row)); - float4 b4 = (tc.zzzz <= d4) ? (0.0f).xxxx : (1.0f).xxxx; - - blockerCount += dot(b4, (1.0f).xxxx); - avgBlockerDepth += dot(d4, b4); - } - } -#else // SM_4_0 - uint vmask[FS + 1]; - - [unroll] for (col = 0; col <= FS; ++col) vmask[col] = uint(0); - - [unroll(11)] for (row = -FS2; row <= FS2; row += 2) - { - [unroll] for (int col = -FS2; col <= FS2; col += 2) - { - float4 d4; - float b; - - d4.w = s_smap.SampleLevel(smp_nofilter, tc.xy, 0, int2(col, row)).x; - b = (tc.z <= d4.w) ? (0.0f) : (1.0f); - vmask[col + FS2 + 0] += ((tc.z <= d4.w) ? (uint(1) << uint(row + FS2 + 0)) : uint(0)); - blockerCount += b; - avgBlockerDepth += d4.w * b; - - d4.z = s_smap.SampleLevel(smp_nofilter, tc.xy, 0, int2(col + 1, row)).x; - b = (tc.z <= d4.z) ? (0.0f) : (1.0f); - vmask[col + FS2 + 1] += ((tc.z <= d4.z) ? (uint(1) << uint(row + FS2 + 0)) : uint(0)); - blockerCount += b; - avgBlockerDepth += d4.z * b; - - d4.x = s_smap.SampleLevel(smp_nofilter, tc.xy, 0, int2(col, row + 1)).x; - vmask[col + FS2 + 0] += ((tc.z <= d4.x) ? (uint(1) << uint(row + FS2 + 1)) : uint(0)); - b = (tc.z <= d4.x) ? (0.0f) : (1.0f); - blockerCount += b; - avgBlockerDepth += d4.x * b; - - d4.y = s_smap.SampleLevel(smp_nofilter, tc.xy, 0, int2(col + 1, row + 1)).x; - vmask[col + FS2 + 1] += ((tc.z <= d4.y) ? (uint(1) << uint(row + FS2 + 1)) : uint(0)); - b = (tc.z <= d4.y) ? (0.0f) : (1.0f); - blockerCount += b; - avgBlockerDepth += d4.y * b; - } - } -#endif - - // compute ratio average blocker depth vs. pixel depth - if (blockerCount > 0.0) - { - avgBlockerDepth /= blockerCount; - fRatio = saturate(((tc.z - avgBlockerDepth) * SUN_WIDTH) / avgBlockerDepth); - fRatio *= fRatio; - } - else - { - fRatio = 0.0; - } - - for (row = 0; row < FS; ++row) - { - for (col = 0; col < FS; ++col) - w += Fw(row, col, fRatio); - } - - // filter shadow map samples using the dynamic weights - [unroll(11)] for (row = -FS2; row <= FS2; row += 2) - { - [unroll] for (int col = -FS2; col <= FS2; col += 2) - { -#if (defined(SM_5)) || (defined(SM_4_1)) -#ifdef SM_5 - v1[(col + FS2) / 2] = s_smap.GatherCmpRed(smp_smap, tc.xy, tc.z, int2(col, row)); -#else // SM_4_1 - float4 d4 = s_smap.Gather(smp_linear, tc.xy, int2(col, row)); - v1[(col + FS2) / 2] = (tc.zzzz <= d4) ? (1.0f).xxxx : (0.0f).xxxx; -#endif -#else - v1[(col + FS2) / 2].w = ((vmask[col + FS2 + 0] & (uint(1) << uint(row + FS2 + 0))) ? 1.0f : 0.0f); - v1[(col + FS2) / 2].z = ((vmask[col + FS2 + 1] & (uint(1) << uint(row + FS2 + 0))) ? 1.0f : 0.0f); - v1[(col + FS2) / 2].x = ((vmask[col + FS2 + 0] & (uint(1) << uint(row + FS2 + 1))) ? 1.0f : 0.0f); - v1[(col + FS2) / 2].y = ((vmask[col + FS2 + 1] & (uint(1) << uint(row + FS2 + 1))) ? 1.0f : 0.0f); -#endif - if (col == -FS2) - { - s += (1 - fc.y) * - (v1[0].w * (Fw(row + FS2, 0, fRatio) - Fw(row + FS2, 0, fRatio) * fc.x) + - v1[0].z * (fc.x * (Fw(row + FS2, 0, fRatio) - Fw(row + FS2, 1, fRatio)) + Fw(row + FS2, 1, fRatio))); - s += (fc.y) * - (v1[0].x * (Fw(row + FS2, 0, fRatio) - Fw(row + FS2, 0, fRatio) * fc.x) + - v1[0].y * (fc.x * (Fw(row + FS2, 0, fRatio) - Fw(row + FS2, 1, fRatio)) + Fw(row + FS2, 1, fRatio))); - if (row > -FS2) - { - s += (1 - fc.y) * - (v0[0].x * (Fw(row + FS2 - 1, 0, fRatio) - Fw(row + FS2 - 1, 0, fRatio) * fc.x) + - v0[0].y * (fc.x * (Fw(row + FS2 - 1, 0, fRatio) - Fw(row + FS2 - 1, 1, fRatio)) + Fw(row + FS2 - 1, 1, fRatio))); - s += (fc.y) * - (v1[0].w * (Fw(row + FS2 - 1, 0, fRatio) - Fw(row + FS2 - 1, 0, fRatio) * fc.x) + - v1[0].z * (fc.x * (Fw(row + FS2 - 1, 0, fRatio) - Fw(row + FS2 - 1, 1, fRatio)) + Fw(row + FS2 - 1, 1, fRatio))); - } - } - else if (col == FS2) - { - s += (1 - fc.y) * - (v1[FS2].w * (fc.x * (Fw(row + FS2, FS - 2, fRatio) - Fw(row + FS2, FS - 1, fRatio)) + Fw(row + FS2, FS - 1, fRatio)) + - v1[FS2].z * fc.x * Fw(row + FS2, FS - 1, fRatio)); - s += (fc.y) * - (v1[FS2].x * (fc.x * (Fw(row + FS2, FS - 2, fRatio) - Fw(row + FS2, FS - 1, fRatio)) + Fw(row + FS2, FS - 1, fRatio)) + - v1[FS2].y * fc.x * Fw(row + FS2, FS - 1, fRatio)); - if (row > -FS2) - { - s += (1 - fc.y) * - (v0[FS2].x * (fc.x * (Fw(row + FS2 - 1, FS - 2, fRatio) - Fw(row + FS2 - 1, FS - 1, fRatio)) + Fw(row + FS2 - 1, FS - 1, fRatio)) + - v0[FS2].y * fc.x * Fw(row + FS2 - 1, FS - 1, fRatio)); - s += (fc.y) * - (v1[FS2].w * (fc.x * (Fw(row + FS2 - 1, FS - 2, fRatio) - Fw(row + FS2 - 1, FS - 1, fRatio)) + Fw(row + FS2 - 1, FS - 1, fRatio)) + - v1[FS2].z * fc.x * Fw(row + FS2 - 1, FS - 1, fRatio)); - } - } - else - { - s += (1 - fc.y) * - (v1[(col + FS2) / 2].w * (fc.x * (Fw(row + FS2, col + FS2 - 1, fRatio) - Fw(row + FS2, col + FS2 + 0, fRatio)) + Fw(row + FS2, col + FS2 + 0, fRatio)) + - v1[(col + FS2) / 2].z * (fc.x * (Fw(row + FS2, col + FS2 - 0, fRatio) - Fw(row + FS2, col + FS2 + 1, fRatio)) + Fw(row + FS2, col + FS2 + 1, fRatio))); - s += (fc.y) * - (v1[(col + FS2) / 2].x * (fc.x * (Fw(row + FS2, col + FS2 - 1, fRatio) - Fw(row + FS2, col + FS2 + 0, fRatio)) + Fw(row + FS2, col + FS2 + 0, fRatio)) + - v1[(col + FS2) / 2].y * (fc.x * (Fw(row + FS2, col + FS2 - 0, fRatio) - Fw(row + FS2, col + FS2 + 1, fRatio)) + Fw(row + FS2, col + FS2 + 1, fRatio))); - if (row > -FS2) - { - s += (1 - fc.y) * - (v0[(col + FS2) / 2].x * - (fc.x * (Fw(row + FS2 - 1, col + FS2 - 1, fRatio) - Fw(row + FS2 - 1, col + FS2 + 0, fRatio)) + Fw(row + FS2 - 1, col + FS2 + 0, fRatio)) + - v0[(col + FS2) / 2].y * - (fc.x * (Fw(row + FS2 - 1, col + FS2 - 0, fRatio) - Fw(row + FS2 - 1, col + FS2 + 1, fRatio)) + Fw(row + FS2 - 1, col + FS2 + 1, fRatio))); - s += (fc.y) * - (v1[(col + FS2) / 2].w * - (fc.x * (Fw(row + FS2 - 1, col + FS2 - 1, fRatio) - Fw(row + FS2 - 1, col + FS2 + 0, fRatio)) + Fw(row + FS2 - 1, col + FS2 + 0, fRatio)) + - v1[(col + FS2) / 2].z * - (fc.x * (Fw(row + FS2 - 1, col + FS2 - 0, fRatio) - Fw(row + FS2 - 1, col + FS2 + 1, fRatio)) + Fw(row + FS2 - 1, col + FS2 + 1, fRatio))); - } - } - if (row != FS2) - v0[(col + FS2) / 2] = v1[(col + FS2) / 2].xy; - } - } - - return s / w; -} - -float4 Fw(int r, int c) { return float4(W0[r][c], W1[r][c], W2[r][c], 1.0f); } - -//====================================================================================== -// This shader computes the contact hardening shadow filter -//====================================================================================== -float shadow_extreme_quality_fused(float3 tc) -{ - float4 s = (0.0f).xxxx; - float2 stc = (SMAP_size * tc.xy) + float2(0.5, 0.5); - float2 tcs = floor(stc); - float2 fc; - int row; - int col; - float w = 0.0; - float avgBlockerDepth = 0; - float blockerCount = 0; - float fRatio; - float4 v1[FS2 + 1]; - float2 v0[FS2 + 1]; - float2 off; - - fc = stc - tcs; - tc.xy = tc.xy - (fc * (1.0f / SMAP_size)); - - // filter shadow map samples using the dynamic weights - [unroll(FS)] for (row = -FS2; row <= FS2; row += 2) - { - for (col = -FS2; col <= FS2; col += 2) - { - float4 d4; - -#ifndef PS_4 - d4 = s_smap.Gather(smp_nofilter, tc.xy + (1.0f / SMAP_size) * float2(col, row)); -#else - d4.w = s_smap.SampleLevel(smp_nofilter, tc.xy + (1.0f / SMAP_size) * float2(col, row), 0).x; - d4.z = s_smap.SampleLevel(smp_nofilter, tc.xy + (1.0f / SMAP_size) * float2(col + 1, row), 0).x; - d4.y = s_smap.SampleLevel(smp_nofilter, tc.xy + (1.0f / SMAP_size) * float2(col + 1, row + 1), 0).x; - d4.x = s_smap.SampleLevel(smp_nofilter, tc.xy + (1.0f / SMAP_size) * float2(col, row + 1), 0).x; -#endif - float4 b4 = (tc.zzzz <= d4) ? (0.0f).xxxx : (1.0f).xxxx; - - v1[(col + FS2) / 2] = (tc.zzzz <= d4) ? (1.0f).xxxx : (0.0f).xxxx; - blockerCount += dot(b4, (1.0).xxxx); - avgBlockerDepth += dot(d4, b4); - - if (col == -FS2) - { - s += (1 - fc.y) * (v1[0].w * (Fw(row + FS2, 0) - Fw(row + FS2, 0) * fc.x) + v1[0].z * (fc.x * (Fw(row + FS2, 0) - Fw(row + FS2, 1)) + Fw(row + FS2, 1))); - s += (fc.y) * (v1[0].x * (Fw(row + FS2, 0) - Fw(row + FS2, 0) * fc.x) + v1[0].y * (fc.x * (Fw(row + FS2, 0) - Fw(row + FS2, 1)) + Fw(row + FS2, 1))); - if (row > -FS2) - { - s += (1 - fc.y) * - (v0[0].x * (Fw(row + FS2 - 1, 0) - Fw(row + FS2 - 1, 0) * fc.x) + v0[0].y * (fc.x * (Fw(row + FS2 - 1, 0) - Fw(row + FS2 - 1, 1)) + Fw(row + FS2 - 1, 1))); - s += (fc.y) * - (v1[0].w * (Fw(row + FS2 - 1, 0) - Fw(row + FS2 - 1, 0) * fc.x) + v1[0].z * (fc.x * (Fw(row + FS2 - 1, 0) - Fw(row + FS2 - 1, 1)) + Fw(row + FS2 - 1, 1))); - } - } - else if (col == FS2) - { - s += (1 - fc.y) * (v1[FS2].w * (fc.x * (Fw(row + FS2, FS - 2) - Fw(row + FS2, FS - 1)) + Fw(row + FS2, FS - 1)) + v1[FS2].z * fc.x * Fw(row + FS2, FS - 1)); - s += (fc.y) * (v1[FS2].x * (fc.x * (Fw(row + FS2, FS - 2) - Fw(row + FS2, FS - 1)) + Fw(row + FS2, FS - 1)) + v1[FS2].y * fc.x * Fw(row + FS2, FS - 1)); - if (row > -FS2) - { - s += (1 - fc.y) * - (v0[FS2].x * (fc.x * (Fw(row + FS2 - 1, FS - 2) - Fw(row + FS2 - 1, FS - 1)) + Fw(row + FS2 - 1, FS - 1)) + v0[FS2].y * fc.x * Fw(row + FS2 - 1, FS - 1)); - s += (fc.y) * - (v1[FS2].w * (fc.x * (Fw(row + FS2 - 1, FS - 2) - Fw(row + FS2 - 1, FS - 1)) + Fw(row + FS2 - 1, FS - 1)) + v1[FS2].z * fc.x * Fw(row + FS2 - 1, FS - 1)); - } - } - else - { - s += (1 - fc.y) * - (v1[(col + FS2) / 2].w * (fc.x * (Fw(row + FS2, col + FS2 - 1) - Fw(row + FS2, col + FS2 + 0)) + Fw(row + FS2, col + FS2 + 0)) + - v1[(col + FS2) / 2].z * (fc.x * (Fw(row + FS2, col + FS2 - 0) - Fw(row + FS2, col + FS2 + 1)) + Fw(row + FS2, col + FS2 + 1))); - s += (fc.y) * - (v1[(col + FS2) / 2].x * (fc.x * (Fw(row + FS2, col + FS2 - 1) - Fw(row + FS2, col + FS2 + 0)) + Fw(row + FS2, col + FS2 + 0)) + - v1[(col + FS2) / 2].y * (fc.x * (Fw(row + FS2, col + FS2 - 0) - Fw(row + FS2, col + FS2 + 1)) + Fw(row + FS2, col + FS2 + 1))); - if (row > -FS2) - { - s += (1 - fc.y) * - (v0[(col + FS2) / 2].x * (fc.x * (Fw(row + FS2 - 1, col + FS2 - 1) - Fw(row + FS2 - 1, col + FS2 + 0)) + Fw(row + FS2 - 1, col + FS2 + 0)) + - v0[(col + FS2) / 2].y * (fc.x * (Fw(row + FS2 - 1, col + FS2 - 0) - Fw(row + FS2 - 1, col + FS2 + 1)) + Fw(row + FS2 - 1, col + FS2 + 1))); - s += (fc.y) * - (v1[(col + FS2) / 2].w * (fc.x * (Fw(row + FS2 - 1, col + FS2 - 1) - Fw(row + FS2 - 1, col + FS2 + 0)) + Fw(row + FS2 - 1, col + FS2 + 0)) + - v1[(col + FS2) / 2].z * (fc.x * (Fw(row + FS2 - 1, col + FS2 - 0) - Fw(row + FS2 - 1, col + FS2 + 1)) + Fw(row + FS2 - 1, col + FS2 + 1))); - } - } - - if (row != FS2) - { - v0[(col + FS2) / 2] = v1[(col + FS2) / 2].xy; - } - } - } - - // compute ratio using formulas from PCSS - if (blockerCount > 0.0) - { - avgBlockerDepth /= blockerCount; - fRatio = saturate(((tc.z - avgBlockerDepth) * SUN_WIDTH) / avgBlockerDepth); - fRatio *= fRatio; - } - else - { - fRatio = 0.0; - } - - // sum up weights of dynamic filter matrix - for (row = 0; row < FS; ++row) - { - for (col = 0; col < FS; ++col) - { - w += Fw(row, col, fRatio); - } - } - - return dot(s, - float4((1.0f - fRatio) * (1.0f - fRatio) * (1.0f - fRatio), 3.0f * (1.0 - fRatio) * (1.0 - fRatio) * fRatio, 3.0f * fRatio * fRatio * (1.0 - fRatio), - fRatio * fRatio * fRatio)) / - w; -} -#endif - -#ifdef SM_4_1 - -float dx10_1_hw_hq_7x7(float3 tc) -{ - float s = 0.0f; - float2 stc = (SMAP_size * tc.xy) + float2(0.5, 0.5); - float2 tcs = floor(stc); - float2 fc; - int row; - int col; - - fc.xy = stc - tcs; - tc.xy = tcs * (1.0 / SMAP_size); - - // loop over the rows - for (row = -GS2; row <= GS2; row += 2) - { - [unroll] for (col = -GS2; col <= GS2; col += 2) - { - float4 v = (tc.zzzz <= s_smap.Gather(smp_nofilter, tc.xy, int2(col, row))) ? (1.0).xxxx : (0.0).xxxx; - - if (row == -GS2) // top row - { - if (col == -GS2) // left - s += dot(float4(1.0 - fc.x, 1.0, 1.0 - fc.y, (1.0 - fc.x) * (1.0 - fc.y)), v); - else if (col == GS2) // right - s += dot(float4(1.0f, fc.x, fc.x * (1.0 - fc.y), 1.0 - fc.y), v); - else // center - s += dot(float4(1.0, 1.0, 1.0 - fc.y, 1.0 - fc.y), v); - } - else if (row == GS2) // bottom row - { - if (col == -GS2) // left - s += dot(float4((1.0 - fc.x) * fc.y, fc.y, 1.0, (1.0 - fc.x)), v); - else if (col == GS2) // right - s += dot(float4(fc.y, fc.x * fc.y, fc.x, 1.0), v); - else // center - s += dot(float4(fc.yy, 1.0, 1.0), v); - } - else // center rows - { - if (col == -GS2) // left - s += dot(float4((1.0 - fc.x), 1.0, 1.0, (1.0 - fc.x)), v); - else if (col == GS2) // right - s += dot(float4(1.0, fc.x, fc.x, 1.0), v); - else // center - s += dot((1.0).xxxx, v); - } - } - } - - return s * (1.0 / 49.0); -} - -#endif - -float dx10_0_hw_hq_7x7(float4 tc) -{ - tc.xyz /= tc.w; - - float s = 0.0; - float2 stc = (SMAP_size * tc.xy) + float2(0.5, 0.5); - float2 tcs = floor(stc); - float2 fc; - - fc = stc - tcs; - tc.xy = tc.xy - (fc * (1.0 / SMAP_size)); - - float2 pwAB = ((2.0).xx - fc); - float2 tcAB = (1.0 / SMAP_size).xx / pwAB; - float2 tcM = (0.5 / SMAP_size).xx; - float2 pwGH = ((1.0).xx + fc); - float2 tcGH = (1.0 / SMAP_size) * (fc / pwGH); - - for (int row = -GS2; row <= GS2; row += 2) - { - for (int col = -GS2; col <= GS2; col += 2) - { - if (row == -GS2) // top row - { - if (col == -GS2) // left - s += (pwAB.x * pwAB.y) * s_smap.SampleCmpLevelZero(smp_smap, tc.xy + tcAB, tc.z, int2(col, row)).x; - else if (col == GS2) // right - s += (pwGH.x * pwAB.y) * s_smap.SampleCmpLevelZero(smp_smap, tc.xy + float2(tcGH.x, tcAB.y), tc.z, int2(col, row)).x; - else // center - s += (2.0 * pwAB.y) * s_smap.SampleCmpLevelZero(smp_smap, tc.xy + float2(tcM.x, tcAB.y), tc.z, int2(col, row)).x; - } - else if (row == GS2) // bottom row - { - if (col == -GS2) // left - s += (pwAB.x * pwGH.y) * s_smap.SampleCmpLevelZero(smp_smap, tc.xy + float2(tcAB.x, tcGH.y), tc.z, int2(col, row)).x; - else if (col == GS2) // right - s += (pwGH.x * pwGH.y) * s_smap.SampleCmpLevelZero(smp_smap, tc.xy + tcGH, tc.z, int2(col, row)).x; - else // center - s += (2.0 * pwGH.y) * s_smap.SampleCmpLevelZero(smp_smap, tc.xy + float2(tcM.x, tcGH.y), tc.z, int2(col, row)).x; - } - else // center rows - { - if (col == -GS2) // left - s += (pwAB.x * 2.0) * s_smap.SampleCmpLevelZero(smp_smap, tc.xy + float2(tcAB.x, tcM.y), tc.z, int2(col, row)).x; - else if (col == GS2) // right - s += (pwGH.x * 2.0) * s_smap.SampleCmpLevelZero(smp_smap, tc.xy + float2(tcGH.x, tcM.y), tc.z, int2(col, row)).x; - else // center - s += (2.0 * 2.0) * s_smap.SampleCmpLevelZero(smp_smap, tc.xy + tcM, tc.z, int2(col, row)).x; - } - } - } - - return s / 49.0; -} - #ifdef SM_MINMAX bool cheap_reject(float3 tc, inout bool full_light) { @@ -536,42 +89,98 @@ bool cheap_reject(float3 tc, inout bool full_light) } } +// Sunshafts +float shadow_dx10_1_sunshafts(float4 tc, float2 pos2d) +{ + float3 t = tc.xyz / tc.w; + float minmax = s_smap_minmax.SampleLevel(smp_nofilter, t, 0).x; + bool umbra = ((minmax.x < 0) && (t.z > -minmax.x)); + + [branch] if (umbra) { return 0.0; } + else { return shadow_hw(tc); } +} #endif // SM_MINMAX -float shadow_hw_hq(float4 tc) +// PCSS shadows +static const float2 poissonDisk[32] = { + float2(0.0617981, 0.07294159), float2(0.6470215, 0.7474022), float2(-0.5987766, -0.7512833), float2(-0.693034, 0.6913887), float2(0.6987045, -0.6843052), + float2(-0.9402866, 0.04474335), float2(0.8934509, 0.07369385), float2(0.1592735, -0.9686295), float2(-0.05664673, 0.995282), float2(-0.1203411, -0.1301079), + float2(0.1741608, -0.1682285), float2(-0.09369049, 0.3196758), float2(0.185363, 0.3213367), float2(-0.1493771, -0.3147511), float2(0.4452095, 0.2580113), + float2(-0.1080467, -0.5329178), float2(0.1604507, 0.5460774), float2(-0.4037193, -0.2611179), float2(0.5947998, -0.2146744), float2(0.3276062, 0.9244621), + float2(-0.6518704, -0.2503952), float2(-0.3580975, 0.2806469), float2(0.8587891, 0.4838005), float2(-0.1596546, -0.8791054), float2(-0.3096867, 0.5588146), + float2(-0.5128918, 0.1448544), float2(0.8581337, -0.424046), float2(0.1562584, -0.5610626), float2(-0.7647934, 0.2709858), float2(-0.3090832, 0.9020988), + float2(0.3935608, 0.4609676), float2(0.3929337, -0.5010948), +}; + +// Quality tokens --Fine +#if !defined(SUN_QUALITY) +#define PCSS_NUM_SAMPLES int(1) +#elif SUN_QUALITY == 1 +#define PCSS_NUM_SAMPLES int(8) +#elif SUN_QUALITY == 2 +#define PCSS_NUM_SAMPLES int(12) +#elif SUN_QUALITY == 3 +#define PCSS_NUM_SAMPLES int(20) +#elif (SUN_QUALITY == 4 || SUN_QUALITY == 5) +#define PCSS_NUM_SAMPLES int(32) +#endif + +float shadow_pcss(float4 tc) { -#ifdef SM_MINMAX - bool full_light = false; - bool cheap_path = cheap_reject(tc.xyz / tc.w, full_light); + // - Small modification to fix flickering and black squares. + // - Added a extra performance option with lower SUN_QUALITY settings. + // - Extended the blocker search from 3x3 to 4x4 for better results. + // https://www.moddb.com/mods/stalker-anomaly/addons/screen-space-shaders/ - [branch] if (cheap_path) + tc.xyz /= tc.w; + +#if SUN_QUALITY > 3 // Blocker search ( Penumbra ) and filter + + int3 uv = int3(tc.xy * float(SMAP_size), 0); + float zBlock = tc.z - 0.0001; + float avgBlockerDepth = 0.0; + float blockerCount = 0.0; + + [unroll] for (int row = -PCSS_PIXEL; row <= PCSS_PIXEL; row += PCSS_STEP) { - [branch] if (full_light == true) return 1.0; - else return sample_hw_pcf(tc, (0).xxxx); + [unroll] for (int col = -PCSS_PIXEL; col <= PCSS_PIXEL; col += PCSS_STEP) + { + float shadowMapDepth = s_smap.Load(uv, int2(col, row)).x; + float b1 = (shadowMapDepth < zBlock) ? 1.0 : 0.0; + blockerCount += b1; + avgBlockerDepth += shadowMapDepth * b1; + } } - else + + if (blockerCount < 1) + return 1.0; + + avgBlockerDepth /= blockerCount; + float fRatio = saturate(((tc.z - avgBlockerDepth) * PCSS_SUN_WIDTH) / avgBlockerDepth); + fRatio *= fRatio; + fRatio = max(PCSS_PIXEL_MIN, fRatio * float(PCSS_PIXEL)) / float(SMAP_size); + + float s = 0.0; + [unroll] for (uint i = 0; i < PCSS_NUM_SAMPLES; ++i) { -#if SUN_QUALITY >= 4 // extreme quality - return shadow_extreme_quality(tc.xyz / tc.w); -#else // SUN_QUALITY<4 -#ifdef SM_4_1 - return dx10_1_hw_hq_7x7(tc.xyz / tc.w); -#else // SM_4_1 - return dx10_0_hw_hq_7x7(tc); -#endif // SM_4_1 -#endif // SUN_QUALITY==4 + float2 offset = poissonDisk[i] * fRatio; + s += s_smap.SampleCmpLevelZero(smp_smap, tc.xy + offset, tc.z).x; } -#else // SM_MINMAX -#if SUN_QUALITY >= 4 // extreme quality - return shadow_extreme_quality(tc.xyz / tc.w); -#else // SUN_QUALITY<4 -#ifdef SM_4_1 - return dx10_1_hw_hq_7x7(tc.xyz / tc.w); -#else // SM_4_1 - return dx10_0_hw_hq_7x7(tc); -#endif // SM_4_1 -#endif // SUN_QUALITY==4 -#endif // SM_MINMAX + return s / PCSS_NUM_SAMPLES; + +#else // No blocker search ( Penumbra ), just filter + + float fRatio = max(PCSS_PIXEL_MIN, 0.5f * float(PCSS_PIXEL)) / float(SMAP_size); + + float s = 0.0; + [unroll] for (uint i = 0; i < PCSS_NUM_SAMPLES; ++i) + { + float2 offset = poissonDisk[i] * fRatio; + s += s_smap.SampleCmpLevelZero(smp_smap, tc.xy + offset, tc.z).x; + } + return s / PCSS_NUM_SAMPLES; + +#endif } ////////////////////////////////////////////////////////////////////////////////////////// @@ -580,91 +189,43 @@ float shadow_hw_hq(float4 tc) float4 test(float4 tc, float2 offset) { - // float4 tcx = float4 (tc.xy + tc.w*offset, tc.zw); - // return tex2Dproj (s_smap,tcx); - tc.xyz /= tc.w; tc.xy += offset; return s_smap.SampleCmpLevelZero(smp_smap, tc.xy, tc.z).x; } -/*half shadowtest_sun (float4 tc, float4 tcJ) // jittered sampling -{ - half4 r; - - const float scale = (0.5f/float(SMAP_size)); - - float texsize = 2*SMAP_size; - float2 tc_J = tc.xy/tc.w*texsize/8.0f; - float2 fr = frac(tc_J)*.5f; - -// half4 J0 = tex2D (jitter0,fr)*scale; -// half4 J1 = tex2D (jitter1,fr)*scale*2; - float4 J0 = jitter0.Sample( smp_jitter, fr )*scale; -// float4 J1 = jitter1.Sample( smp_jitter, fr )*scale; - - float k = 0.99f/float(SMAP_size); - r.x = test (tc,J0.xy+float2(-k,-k)).x; - r.y = test (tc,J0.wz+float2( k,-k)).y; - - r.z = test (tc,J0.xy+float2(-k, k)).z; - r.w = test (tc,J0.wz+float2( k, k)).x; - - half4 f; - float k1 = 1.5f/float(SMAP_size); - f.x = test (tc,-J0.xy+float2(-k1,0)).x; - f.y = test (tc,-J0.wz+float2( 0,-k1)).y; - - f.z = test (tc,-J0.xy+float2( k1, 0)).z; - f.w = test (tc,-J0.wz+float2( 0, k1)).x; - - half res = ( r.x + r.y + r.z + r.w + f.x + f.y + f.z + f.w )*1.h/(4.h + 4.h ); - return res; -}*/ half shadowtest_sun(float4 tc, float4 tcJ) // jittered sampling { half4 r; + const float scale = (0.7 / float(SMAP_size)); - // const float scale = (2.0f/float(SMAP_size)); - const float scale = (0.7f / float(SMAP_size)); - - float2 tc_J = frac(tc.xy / tc.w * SMAP_size / 4.0f) * .5f; + float2 tc_J = frac(tc.xy / tc.w * SMAP_size / 4.0) * 0.5; float4 J0 = jitter0.Sample(smp_jitter, tc_J) * scale; - // half4 J1 = tex2D (jitter1,tc_J)*scale; - const float k = .5f / float(SMAP_size); + const float k = 0.5 / float(SMAP_size); r.x = test(tc, J0.xy + half2(-k, -k)).x; r.y = test(tc, J0.wz + half2(k, -k)).y; r.z = test(tc, -J0.xy + half2(-k, k)).z; r.w = test(tc, -J0.wz + half2(k, k)).x; - return dot(r, 1.h / 4.h); + return dot(r, 1.0 / 4.0); } -half shadow_high(float4 tc) // jittered sampling +float shadow_hw_hq(float4 tc) { - const float scale = (0.5f / float(SMAP_size)); - - float2 tc_J = frac(tc.xy / tc.w * SMAP_size / 4.0f) * .5f; - float4 J0 = jitter0.Sample(smp_jitter, tc_J) * scale; - - const float k = 1.f / float(SMAP_size); - half4 r; - r.x = test(tc, J0.xy + half2(-k, -k)).x; - r.y = test(tc, J0.wz + half2(k, -k)).y; - - r.z = test(tc, J0.xy + half2(-k, k)).z; - r.w = test(tc, J0.wz + half2(k, k)).x; - - const float k1 = 1.3f / float(SMAP_size); - half4 r1; - r1.x = test(tc, -J0.xy + half2(-k1, 0)).x; - r1.y = test(tc, -J0.wz + half2(0, -k1)).y; - - r1.z = test(tc, -2 * J0.xy + half2(k1, 0)).z; - r1.w = test(tc, -2 * J0.wz + half2(0, k1)).x; +#ifdef SM_MINMAX + bool full_light = false; + bool cheap_path = cheap_reject(tc.xyz / tc.w, full_light); - return (r.x + r.y + r.z + r.w + r1.x + r1.y + r1.z + r1.w) * 1.h / 8.h; + [branch] if (cheap_path) + { + [branch] if (full_light == true) return 1.0; + else return sample_hw_pcf(tc, (0).xxxx); + } + else { return shadow_pcss(tc); } +#else // SM_MINMAX + return shadow_pcss(tc); +#endif // SM_MINMAX } float shadow(float4 tc) @@ -676,69 +237,19 @@ float shadow(float4 tc) return shadow_hw_hq(tc); #endif #else -#if SUN_QUALITY >= 2 // Hight quality - // return shadowtest_sun ( tc, float4(0,0,0,0) ); // jittered sampling; - return shadow_hw(tc); -#else - return shadow_hw(tc); -#endif + return shadow_pcss(tc); #endif } -float shadow_volumetric(float4 tc) { return sample_hw_pcf(tc, float4(-1, -1, 0, 0)); } - -#ifdef SM_MINMAX - -////////////////////////////////////////////////////////////////////////////////////////// -// hardware + PCF -////////////////////////////////////////////////////////////////////////////////////////// - -float shadow_dx10_1(float4 tc, float2 tcJ, float2 pos2d) { return shadow(tc); } - -float shadow_dx10_1_sunshafts(float4 tc, float2 pos2d) -{ - float3 t = tc.xyz / tc.w; - float minmax = s_smap_minmax.SampleLevel(smp_nofilter, t, 0).x; - bool umbra = ((minmax.x < 0) && (t.z > -minmax.x)); - - [branch] if (umbra) { return 0.0; } - else { return shadow_hw(tc); } -} - -#endif - ////////////////////////////////////////////////////////////////////////////////////////// // testbed -// uniform sampler2D jitter0; -// uniform sampler2D jitter1; -float shadowtest(float4 tc, float4 tcJ) // jittered sampling -{ - float4 r; - - const float scale = (2.7f / float(SMAP_size)); - - // float4 J0 = tex2Dproj (jitter0,tcJ)*scale; - // float4 J1 = tex2Dproj (jitter1,tcJ)*scale; - tcJ.xy /= tcJ.w; - float4 J0 = jitter0.Sample(smp_jitter, tcJ) * scale; - float4 J1 = jitter1.Sample(smp_jitter, tcJ) * scale; - - r.x = test(tc, J0.xy).x; - r.y = test(tc, J0.wz).y; - r.z = test(tc, J1.xy).z; - r.w = test(tc, J1.wz).x; - - return dot(r, 1.h / 4.h); -} - float shadow_rain(float4 tc, float2 tcJ) // jittered sampling { float4 r; - const float scale = (4.0f / float(SMAP_size)); - // float4 J0 = jitter0.Sample( smp_jitter, tcJ )*scale; - // float4 J1 = jitter1.Sample( smp_jitter, tcJ )*scale; + const float scale = (4.0 / float(SMAP_size)); + float4 J0 = jitter0.Sample(smp_linear, tcJ) * scale; float4 J1 = jitter1.Sample(smp_linear, tcJ) * scale; @@ -746,27 +257,30 @@ float shadow_rain(float4 tc, float2 tcJ) // jittered sampling r.y = test(tc, J0.wz).y; r.z = test(tc, J1.xy).z; r.w = test(tc, J1.wz).x; - - // float4 J0 = jitterMipped.Sample( smp_base, tcJ )*scale; - - // r.x = test (tc,J0.xy).x; - // r.y = test (tc,J0.wz).y; - // r.z = test (tc,J0.yz).z; - // r.w = test (tc,J0.xw).x; - - return dot(r, 1.h / 4.h); + return dot(r, 1.0 / 4.0); } ////////////////////////////////////////////////////////////////////////////////////////// uniform float3x4 m_sunmask; // ortho-projection #ifdef USE_SUNMASK +float4 sun_shafts_intensity; + float sunmask(float4 P) { float2 tc = mul(m_sunmask, P); - return s_lmap.SampleLevel(smp_linear, tc, 0).w; //Hemi map - ambient occlusion + float sunmask = s_lmap.SampleLevel(smp_linear, tc, 0).w; + float sunmask_correction; + + const float intensity = 0.6, ss_bebuff = 10; + + sunmask = sunmask * intensity + (1.0 - intensity); + sunmask_correction = saturate(sun_shafts_intensity.x * ss_bebuff); + + sunmask = lerp(sunmask, 1.0h, sunmask_correction); + return sunmask; } #else -float sunmask(float4 P) { return 1.h; } // +float sunmask(float4 P) { return 1.0; } // #endif ////////////////////////////////////////////////////////////////////////////////////////// uniform float4x4 m_shadow; diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/shadow_direct_tree.vs b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/shadow_direct_tree.vs index dd985f9de7..d6bda4d602 100644 --- a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/shadow_direct_tree.vs +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/shadow_direct_tree.vs @@ -1,3 +1,11 @@ +/** + * @ Version: SCREEN SPACE SHADERS - UPDATE 19 + * @ Description: Trees - Shadows + * @ Modified time: 2023-11-12 09:27 + * @ Author: https://www.moddb.com/members/ascii1457 + * @ Mod: https://www.moddb.com/mods/stalker-anomaly/addons/screen-space-shaders + */ + #include "common.h" uniform float3x4 m_xform; @@ -5,6 +13,7 @@ uniform float3x4 m_xform_v; uniform float4 consts; // {1/quant,1/quant,???,???} uniform float4 c_scale, c_bias, wind, wave; +#include "screenspace_wind.h" ////////////////////////////////////////////////////////////////////////////////////////// // Vertex #ifdef USE_AREF @@ -24,30 +33,30 @@ v2p_shadow_direct main(v_shadow_direct I) // float base = m_xform._24; // take base height from matrix - float dp = calc_cyclic(wave.w + dot(pos, (float3)wave)); float H = pos.y - base; // height of vertex (scaled, rotated, etc.) - float inten = H * dp; // intensity - float2 result; + float2 tc = 0; + float3 wind_result = 0; #ifdef USE_TREEWAVE - result = 0; + wind_result = 0; #else // USE_TREEWAVE #ifdef USE_AREF - float frac = I.tc.z * consts.x; // fractional (or rigidity) -#else // USE_AREF - float frac = 0; -#endif // USE_AREF - result = calc_xz_wave(wind.xz * inten, frac); -#endif // USE_TREEWAVE + tc = (I.tc * consts).xy; + wind_result = ssfx_wind_tree_branches(pos, H, tc.y, ssfx_wind_setup()); +#else + wind_result.xz = ssfx_wind_tree_trunk(pos, H, ssfx_wind_setup()).xy; +#endif + +#endif - float4 f_pos = float4(pos.x + result.x, pos.y, pos.z + result.y, 1); + float4 f_pos = float4(pos.xyz + wind_result.xyz, 1); O.hpos = mul(m_VP, f_pos); #ifdef USE_AREF - O.tc0 = (I.tc * consts).xy; // + result; + O.tc0 = tc; #endif // USE_AREF #ifndef USE_HWSMAP O.depth = O.hpos.z; #endif return O; } -FXVS; +FXVS; \ No newline at end of file diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/shared/common.h b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/shared/common.h index 1d1352d9a9..8d0c420f55 100644 --- a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/shared/common.h +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/shared/common.h @@ -45,7 +45,11 @@ cbuffer static_globals uniform float4 pos_decompression_params2; uniform float4 parallax; + uniform float4 rain_params; // x = raindensity, y = wetness uniform float4 screen_res; // Screen resolution (x-Width,y-Height, zw - 1/resolution) + + uniform float4 pp_img_corrections; + uniform float4 pp_img_cg; } float calc_cyclic(float x) diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/sky2.ps b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/sky2.ps index 9b5e769654..9acb0e4c0a 100644 Binary files a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/sky2.ps and b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/sky2.ps differ diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/sky2.vs b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/sky2.vs index 09d1d8a6db..65e1fc7a57 100644 --- a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/sky2.vs +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/sky2.vs @@ -11,7 +11,7 @@ struct vi struct v2p { float4 c : COLOR0; - float3 tc0 : TEXCOORD0; + float4 tc0 : TEXCOORD0; float3 tc1 : TEXCOORD1; float4 hpos : SV_Position; }; @@ -19,17 +19,23 @@ struct v2p v2p main(vi v) { v2p o; + // v.c.rgb = v.c.bgr; // fix skybox color - float4 tpos = mul(1000, v.p); - o.hpos = mul(m_WVP, tpos); // xform, input in world coords, 1000 - magic number + float4 tpos = float4(2000 * v.p.x, 2000 * v.p.y, 2000 * v.p.z, 2000 * v.p.w); + o.hpos = mul(m_WVP, tpos); o.hpos.z = o.hpos.w; - o.tc0 = v.tc0; // copy tc - o.tc1 = v.tc1; // copy tc - // float scale = tex2Dlod (s_tonemap,float4(.5,.5,.5,.5)).x ; + o.tc0.xyz = v.tc0; // copy tc + o.tc1.xyz = v.tc1; // copy tc float scale = s_tonemap.Load(int3(0, 0, 0)).x; - // float scale = s_tonemap.Load( int3(1,1,0) ).x; - // o.c = float4 ( v.c.rgb*(scale*1.7), v.c.a ); // copy color, pre-scale by tonemap //float4 ( v.c.rgb*scale*2, v.c.a ); - o.c = float4(v.c.rgb * (scale * 2.0), v.c.a); // copy color, pre-scale by tonemap //float4 ( v.c.rgb*scale*2, v.c.a ); + + float3 tint = v.c.rgb * 1.7; + + // float3 tint = 1.0; + // float3 tint = env_color.rgb; + // float3 tint = fog_color.rgb * 2.0; + + o.c = float4(tint, v.c.a); // copy color, pre-scale by tonemap //float4 (v.c.rgb*scale*2, v.c.a ); + o.tc0.w = scale; return o; } \ No newline at end of file diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/sload.h b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/sload.h index 09015210b8..d7de825ee8 100644 --- a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/sload.h +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/sload.h @@ -1,3 +1,11 @@ +#define USE_ERROR_CORRECTION +//#define RECALCULATENORMALZ +//#define NORMALIZE_TEXTURES +static const float NORMAL_STRENGTH = 1.0; +static const float DETAIL_STRENGTH = 1.0; +static const float DETAIL_TINT = 1.0; +static const float DETAIL_GLOSS = 1.0; + #ifndef SLOAD_H #define SLOAD_H @@ -15,6 +23,62 @@ static const float2 MSAAOffsets[8] = {float2(1, -3), float2(-1, 3), float2(5, 1) #endif #endif // MSAA_ALPHATEST_DX10_1 +////////////////////////////////////////////////////////////////////////////////////////// +// Texture samplers and blenders // +////////////////////////////////////////////////////////////////////////////////////////// + +float3 SampleNormal(float4 N, float4 NE) +{ + float3 Norm = unpack_normal(N.wzy); +#ifdef USE_ERROR_CORRECTION + Norm += unpack_normal(NE.xyz); +#endif +#ifdef RECALCULATENORMALZ + Norm.z = sqrt(1 - saturate(dot(Norm.xy, Norm.xy))); +#endif +#ifdef NORMALIZE_TEXTURES + Norm = normalize(Norm); +#endif + return Norm; +} + +float3 NormalStrength(float3 N, float Strength) +{ + if (Strength != 1.0) + { + N.xy *= Strength; + N.z = sqrt(1 - saturate(dot(N.xy, N.xy))); + N = normalize(N); + } + return N; +} + +float SampleGloss(float4 N) { return N.x; } + +float SampleHeight(float4 NE) { return NE.w; } + +float3 ApplyDetailAlbedo(float3 A1, float3 A2) +{ + // return saturate(A1 * A2 * 2); + return saturate(A1 * exp2(DETAIL_TINT * (A2 * 2 - 1))); +} + +float3 ApplyDetailNormal(float3 N1, float3 N2) +{ + N1 += float3(0, 0, 1); + N2 *= float3(-1, -1, 1); + return normalize(N1 * dot(N1, N2) / N1.z - N2); +} + +float ApplyDetailGloss(float G1, float G2) +{ + // return saturate(G1 * G2 * 2); + // return saturate(G1 + (DETAIL_GLOSS * (G2 * 2 - 1))); + return saturate(G1 * exp2(DETAIL_GLOSS * (G2 * 2 - 1))); +} + +float ApplyDetailHeight(float H1, float H2) { return H1 + (H2 * 2 - 1); } + ////////////////////////////////////////////////////////////////////////////////////////// // Bumped surface loader // ////////////////////////////////////////////////////////////////////////////////////////// @@ -30,73 +94,90 @@ float4 tbase(float2 tc) { return s_base.Sample(smp_base, tc); } #if defined(ALLOW_STEEPPARALLAX) && defined(USE_STEEPPARALLAX) -static const float fParallaxStartFade = 8.0f; -static const float fParallaxStopFade = 12.0f; +// Always remember to check defines, variables, and shit.... god +#define PARALLAX_NEAR_PLANE 0.01 +#define PARALLAX_FAR_PLANE 35 +#define PARALLAX_DEPTH 0.045 +// Ok, we can comment old gsc parallax now. +// We need to change input, to p_bumped struct like in GSC shader +// We also change name of this function to GSC +// Time to change input to stuff from p_bumped. void UpdateTC(inout p_bumped I) { - if (I.position.z < fParallaxStopFade) + // Here's "limited" range of parallax. We use linear depth (z vector of view space position) to do that + if ((I.position.z > PARALLAX_NEAR_PLANE) && (I.position.z < PARALLAX_FAR_PLANE)) { - const float maxSamples = 25; - const float minSamples = 5; - const float fParallaxOffset = -0.013; + // That M1/M2/M3 stuff is our TBN matrix (we aligin tangent normals/vectors to to just geometry normals + float3 eye = normalize(mul(float3x3(I.M1.x, I.M2.x, I.M3.x, I.M1.y, I.M2.y, I.M3.y, I.M1.z, I.M2.z, I.M3.z), -I.position.xyz)); + + // steps minmax and refines minmax + int4 steps = int4(3, 10, 7, 16); // 3..10, 7..16 - float3 eye = mul(float3x3(I.M1.x, I.M2.x, I.M3.x, I.M1.y, I.M2.y, I.M3.y, I.M1.z, I.M2.z, I.M3.z), -I.position.xyz); + bool need_disp_lerp = true; + bool need_refine = true; // Thats refinement steps, used to smoothout raymarched results - eye = normalize(eye); + float view_angle = abs(dot(float3(0.0, 0.0, 1.0), eye)); - // Calculate number of steps - float nNumSteps = lerp(maxSamples, minSamples, eye.z); + float layer_step = rcp(lerp(steps.y, steps.x, view_angle)); - float fStepSize = 1.0 / nNumSteps; - float2 vDelta = eye.xy * fParallaxOffset * 1.2; - float2 vTexOffsetPerStep = fStepSize * vDelta; + // float2 tc_step = layer_step * eye.xy * PARALLAX_DEPTH); + float2 tc_step = layer_step * eye.xy * (parallax.x); - // Prepare start data for cycle - float2 vTexCurrentOffset = I.tcdh; - float fCurrHeight = 0.0; - float fCurrentBound = 1.0; + // Now, we have to change this huita. p.tcdbump is our "tiled" texture coordinate + // I.tcdh is our "normal" texcoord, lets see above + float2 displaced_tc = I.tcdh; - for (int i = 0; i < nNumSteps; ++i) + float curr_disp, curr_layer = 0.0; + + do + { + displaced_tc -= tc_step; + curr_disp = 1 - s_bumpX.SampleLevel(smp_base, displaced_tc, 0).w; // Our heightmap sampler + curr_layer += layer_step; + } while (curr_layer < curr_disp); + + if (need_refine) { - if (fCurrHeight < fCurrentBound) + displaced_tc += tc_step; + curr_layer -= layer_step; + + float refine_steps = lerp(steps.w, steps.z, view_angle); + + tc_step /= refine_steps; + layer_step /= refine_steps; + + do { - vTexCurrentOffset += vTexOffsetPerStep; - fCurrHeight = s_bumpX.SampleLevel(smp_base, vTexCurrentOffset.xy, 0).a; - fCurrentBound -= fStepSize; - } + displaced_tc -= tc_step; + curr_disp = 1.0 - s_bumpX.SampleLevel(smp_base, displaced_tc, 0).w; + curr_layer += layer_step; + } while (curr_layer < curr_disp); } - /* - [unroll(25)] // Doesn't work with [loop] - for( ;fCurrHeight < fCurrentBound; fCurrentBound -= fStepSize ) - { - vTexCurrentOffset += vTexOffsetPerStep; - fCurrHeight = s_bumpX.SampleLevel( smp_base, vTexCurrentOffset.xy, 0 ).a; - } - */ - // Reconstruct previouse step's data - vTexCurrentOffset -= vTexOffsetPerStep; - float fPrevHeight = s_bumpX.Sample(smp_base, float3(vTexCurrentOffset.xy, 0)).a; - - // Smooth tc position between current and previouse step - float fDelta2 = ((fCurrentBound + fStepSize) - fPrevHeight); - float fDelta1 = (fCurrentBound - fCurrHeight); - float fParallaxAmount = (fCurrentBound * fDelta2 - (fCurrentBound + fStepSize) * fDelta1) / (fDelta2 - fDelta1); - float fParallaxFade = smoothstep(fParallaxStopFade, fParallaxStartFade, I.position.z); - float2 vParallaxOffset = vDelta * ((1 - fParallaxAmount) * fParallaxFade); - float2 vTexCoord = I.tcdh + vParallaxOffset; - - // Output the result - I.tcdh = vTexCoord; + if (need_disp_lerp) + { + float2 displaced_tc_prev = displaced_tc + tc_step; + + float after_depth = curr_disp - curr_layer; + float before_depth = 1.0 - s_bumpX.SampleLevel(smp_base, displaced_tc_prev, 0).w - curr_layer + layer_step; // Another sampler name + + float weight = after_depth / (after_depth - before_depth); + + displaced_tc = lerp(displaced_tc, displaced_tc_prev, weight); + } + // Tiling for detail/tiled textures #if defined(USE_TDETAIL) && defined(USE_STEEPPARALLAX) - I.tcdbump = vTexCoord * dt_params; + I.tcdbump = I.tcdh * dt_params; // tiled UV + I.tcdbump += displaced_tc - I.tcdh; // offset #endif + + I.tcdh = displaced_tc; } } -#elif defined(USE_PARALLAX) && defined(USE_STEEPPARALLAX) +#elif defined(USE_PARALLAX) || defined(USE_STEEPPARALLAX) void UpdateTC(inout p_bumped I) { @@ -108,6 +189,11 @@ void UpdateTC(inout p_bumped I) height = height * (parallax.x) + (parallax.y); // float2 new_tc = I.tcdh + height * normalize(eye); // + // Tiling for detail/tiled textures +#if defined(USE_TDETAIL) && defined(USE_STEEPPARALLAX) + I.tcdbump = I.tcdh * dt_params + height * normalize(eye); +#endif + // Output the result I.tcdh.xy = new_tc; } @@ -124,101 +210,53 @@ surface_bumped sload_i(p_bumped I) UpdateTC(I); // All kinds of parallax are applied here. - float4 Nu = s_bump.Sample(smp_base, I.tcdh); // IN: normal.gloss - float4 NuE = s_bumpX.Sample(smp_base, I.tcdh); // IN: normal_error.height - - S.base = tbase(I.tcdh); // IN: rgb.a - S.normal = Nu.wzy + (NuE.xyz - 1.0h); // (Nu.wzyx - .5h) + (E-.5) - S.gloss = Nu.x * Nu.x; // S.gloss = Nu.x*Nu.x; - S.height = NuE.w; - // S.height = 0; - + // Base textures + // + S.base = tbase(I.tcdh); + float4 Nu = s_bump.Sample(smp_base, I.tcdh); + float4 NuE = s_bumpX.Sample(smp_base, I.tcdh); + float3 TangentNormal = NormalStrength(SampleNormal(Nu, NuE), NORMAL_STRENGTH); + S.normal = TangentNormal; + S.gloss = SampleGloss(Nu); + S.height = SampleHeight(NuE); + + // Detail textures + // #ifdef USE_TDETAIL + float4 detail = s_detail.Sample(smp_base, I.tcdbump); + S.base.rgb = ApplyDetailAlbedo(S.base.rgb, detail.rgb); #ifdef USE_TDETAIL_BUMP float4 NDetail = s_detailBump.Sample(smp_base, I.tcdbump); float4 NDetailX = s_detailBumpX.Sample(smp_base, I.tcdbump); - S.gloss = S.gloss * NDetail.x * 2; - // S.normal += NDetail.wzy-.5; - S.normal += NDetail.wzy + NDetailX.xyz - 1.0h; // (Nu.wzyx - .5h) + (E-.5) - - float4 detail = s_detail.Sample(smp_base, I.tcdbump); - S.base.rgb = S.base.rgb * detail.rgb * 2; - -// S.base.rgb = float3(1,0,0); -#else // USE_TDETAIL_BUMP - float4 detail = s_detail.Sample(smp_base, I.tcdbump); - S.base.rgb = S.base.rgb * detail.rgb * 2; - S.gloss = S.gloss * detail.w * 2; - -#endif // USE_TDETAIL_BUMP + float3 DetailNormal = NormalStrength(SampleNormal(NDetail, NDetailX), DETAIL_STRENGTH); + S.normal = ApplyDetailNormal(TangentNormal, DetailNormal); + // float DetailGloss = SampleGloss(NDetail); + float DetailGloss = detail.w; // higher res most of the time + float DetailHeight = SampleHeight(NDetailX); + S.height = ApplyDetailHeight(S.height, DetailHeight); +#else + float DetailGloss = detail.w; +#endif + S.gloss = ApplyDetailGloss(S.gloss, DetailGloss); #endif + // return S; } -surface_bumped sload_i(p_bumped I, float2 pixeloffset) -{ - surface_bumped S; +surface_bumped sload(p_bumped I) { return sload_i(I); } +surface_bumped sload(p_bumped I, float2 pixeloffset) +{ // apply offset #ifdef MSAA_ALPHATEST_DX10_1 I.tcdh.xy += pixeloffset.x * ddx(I.tcdh.xy) + pixeloffset.y * ddy(I.tcdh.xy); -#endif - - UpdateTC(I); // All kinds of parallax are applied here. - - float4 Nu = s_bump.Sample(smp_base, I.tcdh); // IN: normal.gloss - float4 NuE = s_bumpX.Sample(smp_base, I.tcdh); // IN: normal_error.height - - S.base = tbase(I.tcdh); // IN: rgb.a - S.normal = Nu.wzyx + (NuE.xyz - 1.0h); // (Nu.wzyx - .5h) + (E-.5) - S.gloss = Nu.x * Nu.x; // S.gloss = Nu.x*Nu.x; - S.height = NuE.w; - // S.height = 0; - #ifdef USE_TDETAIL -#ifdef USE_TDETAIL_BUMP -#ifdef MSAA_ALPHATEST_DX10_1 -#if ((!defined(ALLOW_STEEPPARALLAX)) && defined(USE_STEEPPARALLAX)) I.tcdbump.xy += pixeloffset.x * ddx(I.tcdbump.xy) + pixeloffset.y * ddy(I.tcdbump.xy); #endif #endif - float4 NDetail = s_detailBump.Sample(smp_base, I.tcdbump); - float4 NDetailX = s_detailBumpX.Sample(smp_base, I.tcdbump); - S.gloss = S.gloss * NDetail.x * 2; - // S.normal += NDetail.wzy-.5; - S.normal += NDetail.wzy + NDetailX.xyz - 1.0h; // (Nu.wzyx - .5h) + (E-.5) - - float4 detail = s_detail.Sample(smp_base, I.tcdbump); - S.base.rgb = S.base.rgb * detail.rgb * 2; - -// S.base.rgb = float3(1,0,0); -#else // USE_TDETAIL_BUMP -#ifdef MSAA_ALPHATEST_DX10_1 - I.tcdbump.xy += pixeloffset.x * ddx(I.tcdbump.xy) + pixeloffset.y * ddy(I.tcdbump.xy); -#endif - float4 detail = s_detail.Sample(smp_base, I.tcdbump); - S.base.rgb = S.base.rgb * detail.rgb * 2; - S.gloss = S.gloss * detail.w * 2; -#endif // USE_TDETAIL_BUMP -#endif - - return S; -} - -surface_bumped sload(p_bumped I) -{ - surface_bumped S = sload_i(I); - // S.normal.z *= 0.5; //. make bump twice as contrast (fake, remove me if possible) - return S; -} - -surface_bumped sload(p_bumped I, float2 pixeloffset) -{ - surface_bumped S = sload_i(I, pixeloffset); - // S.normal.z *= 0.5; //. make bump twice as contrast (fake, remove me if possible) - return S; + return sload_i(I); } #endif diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/srgb.h b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/srgb.h new file mode 100644 index 0000000000..484afa65fb --- /dev/null +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/srgb.h @@ -0,0 +1,49 @@ +//================================================================================================= +// Gamma Correction +//================================================================================================= +//#define USE_STRICT_GAMMA_CORRECTION //use gamma correction for sky blending, might distort the original colors +//================================================================================================= + +float LinearTosRGB(float gammaPre) +{ + /* + float Low = gammaPre * 12.92; + float High = (pow(gammaPre, 1.0 / 2.4) * 1.055) - 0.055; + return (gammaPre <= 0.0031308) ? Low : High; + */ + // return (gammaPre <= 0.00313080495356037151702786377709) ? gammaPre * 12.92 : (1.055 * pow(gammaPre, 0.41666666666666666666666666666667) - 0.055); + // return max(1.055 * pow(gammaPre, 0.416666667) - 0.055, 0.0); + + // Cheap sRGB doesn't cause clipping + return pow(gammaPre, 0.45454545); +} + +float3 LinearTosRGB(float3 gammaPre) +{ + gammaPre = max(0.0, gammaPre); + float3 gammaPost = float3(LinearTosRGB(gammaPre.r), LinearTosRGB(gammaPre.g), LinearTosRGB(gammaPre.b)); + return gammaPost; +} + +float SRGBToLinear(float gammaPre) +{ + /* + float Low = gammaPre / 12.92; + float High = pow((gammaPre + 0.055) / 1.055, 2.4); + return(gammaPre <= 0.04045) ? Low : High; + */ + // return (gammaPre <= 0.04045) ? gammaPre * 0.07739938080495356037151702786378 : pow((gammaPre + 0.055) * 0.94786729857819905213270142180095, 2.4); + // return gammaPre * (gammaPre * (gammaPre * 0.305306011 + 0.682171111) + 0.012522878); + + // Cheap sRGB doesn't cause clipping + return pow(gammaPre, 2.2); +} + +float3 SRGBToLinear(float3 gammaPre) +{ + gammaPre = max(0.0, gammaPre); + float3 gammaPost = float3(SRGBToLinear(gammaPre.r), SRGBToLinear(gammaPre.g), SRGBToLinear(gammaPre.b)); + return gammaPost; +} + +#include "tonemap_srgb.h" \ No newline at end of file diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/ssss_mrmnwar_display.ps b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/ssss_mrmnwar_display.ps index 53a2bdc074..18985ccbfb 100644 Binary files a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/ssss_mrmnwar_display.ps and b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/ssss_mrmnwar_display.ps differ diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/tonemap_srgb.h b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/tonemap_srgb.h new file mode 100644 index 0000000000..a1283ff9c2 --- /dev/null +++ b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/tonemap_srgb.h @@ -0,0 +1,40 @@ +//================================================================================================= +// Gamma Correct Tonemapping and Color Grading +#include "ACES.h" +//================================================================================================= + +float3 tonemap_sRGB(float3 x, float w) +{ +#ifdef USE_ACES + // use ACES workflow for color grading and tonemapping + x = ACES(x); +#else + // convert into linear gamma space + x = SRGBToLinear(x); + + // color grading + ACES_LMT(x); + + // clamp negative values + x = max(0.0, x); + + // Boost the contrast to match ACES RRT + float Contrast_Boost = 1.42857; + x = pow(x, Contrast_Boost) * 0.18 / pow(0.18, Contrast_Boost); + + // reinhard tonemapping + x = x / (x + 1); + x /= w / (w + 1); + + // convert into sRGB gamma space + x = LinearTosRGB(x); +#endif + /* + //debug highlights for clipping values + x = x < 0.0 ? float3(0.0,0.0,1.0) : x; + x = x > 1.0 ? float3(1.0,0.0,0.0) : x; + */ + + // return with saturate, everything should be in LDR sRGB + return saturate(x); +} diff --git a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/water.ps b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/water.ps index c1f13291f6..03640fb090 100644 Binary files a/Game/Resources_SoC_1.0006/gamedata/shaders/r3/water.ps and b/Game/Resources_SoC_1.0006/gamedata/shaders/r3/water.ps differ diff --git a/Game/Resources_SoC_1.0006/gamedata/textures/fx/water_sbumpvolume.dds b/Game/Resources_SoC_1.0006/gamedata/textures/fx/water_sbumpvolume.dds index a2c85659ce..4318104d27 100644 Binary files a/Game/Resources_SoC_1.0006/gamedata/textures/fx/water_sbumpvolume.dds and b/Game/Resources_SoC_1.0006/gamedata/textures/fx/water_sbumpvolume.dds differ diff --git a/Game/Resources_SoC_1.0006/gamedata/textures/fx/wind_wave.dds b/Game/Resources_SoC_1.0006/gamedata/textures/fx/wind_wave.dds new file mode 100644 index 0000000000..4bf353cb0b Binary files /dev/null and b/Game/Resources_SoC_1.0006/gamedata/textures/fx/wind_wave.dds differ diff --git a/Game/Resources_SoC_1.0006/gamedata/textures/water/water_sbumpvolume.dds b/Game/Resources_SoC_1.0006/gamedata/textures/water/water_sbumpvolume.dds index 574aecee23..4318104d27 100644 Binary files a/Game/Resources_SoC_1.0006/gamedata/textures/water/water_sbumpvolume.dds and b/Game/Resources_SoC_1.0006/gamedata/textures/water/water_sbumpvolume.dds differ