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

126 lines
3.5 KiB
C
Raw Normal View History

2024-03-17 20:18:03 -04:00
/**
* @ Version: SCREEN SPACE SHADERS - UPDATE 11.3
* @ Description: SSS implementation
* @ Modified time: 2023-12-11 08:23
* @ Author: https://www.moddb.com/members/ascii1457
* @ Mod: https://www.moddb.com/mods/stalker-anomaly/addons/screen-space-shaders
*/
#include "screenspace_common.h"
#include "settings_screenspace_SSS.h"
float SSFX_ScreenSpaceShadows_Far(float4 P, float2 tc, uint iSample)
{
if ( abs(P.w - MAT_FLORA) > 0.03f )
return 1;
// Light vector
float3 L_dir = mul(m_V, float4(-normalize(L_sun_dir_w), 0)).xyz;
RayTrace sss_ray = SSFX_ray_init(P.xyz, L_dir, 2.5, 2, 1);
[unroll (2)]
for (int i = 0; i < 2; i++)
{
// Break the march if ray go out of screen...
if (!SSFX_is_valid_uv(sss_ray.r_pos))
return 1;
// Sample current ray pos ( x = difference | y = sample depth | z = current ray len )
float3 depth_ray = SSFX_ray_intersect(sss_ray, iSample);
// Check depth difference
float diff = depth_ray.x;
// No Sky
diff *= depth_ray.y > SKY_EPS;
// Negative: Ray is closer to the camera ( not occluded )
// Positive: Ray is beyond the depth sample ( occluded )
if (diff > 0 && diff < 3)
{
return 0;
}
// Step the ray
sss_ray.r_pos += sss_ray.r_step;
}
return 1;
}
float SSFX_ScreenSpaceShadows(float4 P, float2 tc, uint iSample)
{
// Light vector
float3 L_dir = mul(m_V, float4(-normalize(L_sun_dir_w), 0)).xyz;
// Material conditions...
bool mat_flora = abs(P.w - MAT_FLORA) <= 0.02f;
bool mat_terrain = abs(P.w - 0.95f) <= 0.02f;
// Weapons mask. Depth below or equal to 1.2
bool weapon_mask = P.z >= 1.2f;
// Weapon Factor.
float pLen = length(P.z);
float wpn_f = smoothstep(G_SSDO_WEAPON_LENGTH * 0.75f, G_SSDO_WEAPON_LENGTH, pLen);
//wpn_f = saturate(wpn_f + mat_terrain);
// Adjust Settings for weapons and scene.
float ray_hardness = lerp(10.0f * G_SSDO_WEAPON_HARDNESS, 15.0f * G_SSDO_SCENARY_HARDNESS, wpn_f);
float ray_detail = clamp(pLen * 0.003f, G_SSS_DETAILS, 10);
float ray_thick = (0.3f - wpn_f * 0.23f) + (pLen * 0.001f * wpn_f);
float ray_len = lerp(G_SSDO_WEAPON_SHADOW_LENGTH, G_SSDO_SCENARY_SHADOW_LENGTH, wpn_f);
// Grass overwrite. ( Sadly some weapons use MAT_FLORA, let's remove low depth values from the overwrite )
if (mat_flora && weapon_mask)
{
ray_hardness = G_SSDO_GRASS_HARDNESS * 5.0f;
ray_len = G_SSDO_GRASS_SHADOW_LENGTH;
}
if (ray_hardness <= 0)
return 1.0f;
RayTrace sss_ray = SSFX_ray_init(P, L_dir, ray_len, G_SSS_STEPS, SSFX_noise(tc));
float fade_len = 1.0f + sss_ray.r_step;
float shadow = 0;
[unroll (G_SSS_STEPS)]
for (int i = 0; i < G_SSS_STEPS; i++)
{
// Break the march if ray go out of screen...
if (!SSFX_is_valid_uv(sss_ray.r_pos))
break;
// Sample current ray pos ( x = difference | y = sample depth | z = current ray len )
float3 depth_ray = SSFX_ray_intersect(sss_ray, iSample);
// Check depth difference
float diff = depth_ray.x;
// No Sky
diff *= depth_ray.y > SKY_EPS;
// Disable weapons at some point to avoid wrong shadows on the ground
if (weapon_mask)
diff *= depth_ray.y >= 1.0f;
// Negative: Ray is closer to the camera ( not occluded )
// Positive: Ray is beyond the depth sample ( occluded )
if (diff > ray_detail && diff < ray_thick)
{
shadow += (fade_len - depth_ray.z) * (1.0f - smoothstep( G_SSS_STEPS * G_SSS_FORCE_FADE, G_SSS_STEPS + 1, i));
}
// Step the ray
sss_ray.r_pos += sss_ray.r_step;
}
// Calc shadow and return.
return 1.0f - saturate(shadow * (1.0f / G_SSS_STEPS) * ray_hardness) * G_SSS_INTENSITY;
}