156 lines
4.8 KiB
C
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));
|
||
|
}
|