Divergent/mods/Screen Space Shaders/gamedata/shaders/r3/screenspace_il.h

156 lines
4.8 KiB
C

/**
* @ Version: SCREEN SPACE SHADERS - UPDATE 14.5
* @ Description: Indirect Light Shader
* @ Modified time: 2023-02-01 07:08
* @ Author: https://www.moddb.com/members/ascii1457
* @ Mod: https://www.moddb.com/mods/stalker-anomaly/addons/screen-space-shaders
*/
#include "settings_screenspace_IL.h"
#ifndef SSFX_READY
#include "screenspace_common.h"
#endif
// Internal Vars
static const int il_quality[4] = { 8, 16, 24, 32 };
// Some vars to fix incompatibilities for the moment...
uniform float4 ssfx_wpn_dof_1;
//uniform float4 fakescope_params3; // Declared on combine_2
float3 ssfx_il_bounce(float3 P, float3 N, float Range, int count, uint iSample)
{
// Use surface normal and add the hemisphere distribution
float3 sample_rays = ssfx_hemisphere[count] + N.xyz;
// Position to sample
float3 occ_pos = P.xyz + sample_rays * Range;
// Sample position to UV
float2 occ_pos_uv = SSFX_view_to_uv(occ_pos);
// Get position buffer to calc normal and get depth
float4 sample_pos = SSFX_get_position(occ_pos_uv, iSample);
// Adjust G_IL_MAX_DIFFERENCE if the sampled pixel is a weapon/hand...
float Maxdiff = sample_pos.z < 1.5f ? 2.0f : G_IL_MAX_DIFFERENCE;
// IL base intensity
float il_intensity = smoothstep(Maxdiff, 0.0f, abs(P.z - sample_pos.z));
// Use Normal to adjust intensity and avoid self IL ( 1 version for MAT FLORA FIXES )
#ifndef SSFX_FLORAFIX
il_intensity *= 1.0 - saturate(dot(gbuf_unpack_normal( sample_pos.xy ), N ));
#else
bool IsFlora = abs(sample_pos.w - MAT_FLORA) <= 0.04f; // Is MAT_FLORA?
il_intensity *= 1.0 - saturate(dot(gbuf_unpack_normal( sample_pos.xy ), N ) - IsFlora); // Discard intensity adjustment if MAT_FLORA
#endif
// Never discard the sample if comes from the sky. We use this for some sort of sky light.
if (is_sky(sample_pos.z))
il_intensity = 1.0f * G_IL_SKYLIGHT_INTENSITY;
// Discard if the final intensity is lower or equal to G_IL_DISCARD_SAMPLE_AT
[branch]
if (il_intensity > G_IL_DISCARD_SAMPLE_AT)
{
// Sample scene color
float3 sample_il = s_blur_8.SampleLevel(smp_rtlinear, occ_pos_uv, 0);
// Adjust intensity using Normal, Difference and sky.
sample_il *= il_intensity;
// Return sample
return sample_il;
}
// Well...
return 0;
}
void ssfx_il(float2 tc, float2 pos2d, float3 P, float3 N, inout float3 color, uint iSample)
{
// Skip Sky. ( Disable when used with Shader Based 2D Scopes )
if (P.z <= SKY_EPS || fakescope_params3.x > 0)
return;
// Discard IL when using NV
#ifdef SSFX_BEEFS_NVG
if (shader_param_8.x > 0)
return;
#endif
// Var to accumulate the IL
float3 il = 0;
// Depth distance. Used for some calcs later
float PLen = length(P);
// Weapon factor to adjust some values for weapons
float WeaponFactor = smoothstep(G_IL_WEAPON_LENGTH * 0.5f, G_IL_WEAPON_LENGTH, PLen);
float il_noise = frac(sin(dot(tc, float2(12.0, 78.0) )) * 43758.0) * G_IL_NOISE;
bool IsWpn = PLen < 1.5;
[unroll (il_quality[G_IL_QUALITY])]
for (int i = 0; i < il_quality[G_IL_QUALITY]; i++)
{
// Adjust weapons range
float range = (G_IL_WEAPON_RANGE + G_IL_RANGE * WeaponFactor) * (1.0f + il_noise);
// Do bounce
il += ssfx_il_bounce(P, N, range, i, iSample);
}
// Normalize result
il /= il_quality[G_IL_QUALITY];
// Fogging
#ifdef SSFX_FOG
float3 WorldP = mul(m_inv_V, float4(P.xyz, 1));
float Fog = saturate(PLen * fog_params.w + fog_params.x);
// Same as SSFX_FOGGING but multiplied * 2
float fog_height = smoothstep(G_FOG_HEIGHT, -G_FOG_HEIGHT, WorldP.y) * G_FOG_HEIGHT_INTENSITY;
float fog_extra = saturate(Fog + fog_height * (Fog * G_FOG_HEIGHT_DENSITY));
float Fade = 1.0f - saturate(fog_extra * 2.0f);
#else
// Vanilla fog calc multiplied * 2
float Fade = 1.0f - saturate((PLen * fog_params.w + fog_params.x) * 2.0f);
#endif
// "Fix" DOF incompatibility ( Reload at the moment... Maybe peripheral blur requires the same? )
Fade *= 1.0f - ssfx_wpn_dof_1.z * smoothstep(1.0f, 2.4f, PLen);
// Screen edge fade ( To avoid some artifacts )
float4 calc_edges = smoothstep(-0.05f, 0.3f, float4(tc.x, 1.0f - tc.x, tc.y, 1.0f - tc.y));
Fade *= calc_edges.x * calc_edges.y * calc_edges.z * calc_edges.w;
// Apply fading. ( Edges + Fog + DOF fix )
il *= Fade * saturate(PLen * 2.0f);
// Vibrance
#ifndef G_IL_DEBUG_MODE
il = vibrance(il, G_IL_COLOR_VIBRANCE);
#else
il = vibrance(il, 100);
#endif
// -- Mix with scene color.
float blendfact = 1.0 - dot(color, LUMINANCE_VECTOR); // Blend factor using LUMINANCE_VECTOR
// Adjust intensity using scene color.
il = il * dot(color, G_IL_INTENSITY) * blendfact * blendfact;
// Check color difference between color and IL.
float colordiff = saturate(normalize(il) - normalize(color));
// Square difference to get a nice falloff curve where a higher difference fall faster than a lower one.
colordiff = sqrt(colordiff);
// Final Mix. Adjust intensity using colordiff.
color = saturate(color + il * (1.0f - colordiff));
}