126 lines
3.5 KiB
C
126 lines
3.5 KiB
C
|
/**
|
||
|
* @ 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;
|
||
|
}
|