142 lines
3.7 KiB
C
142 lines
3.7 KiB
C
/**
|
|
* @ Version: SCREEN SPACE SHADERS - UPDATE 22
|
|
* @ Description: SSS implementation
|
|
* @ Modified time: 2024-11-25 02:19
|
|
* @ Author: https://www.moddb.com/members/ascii1457
|
|
* @ Mod: https://www.moddb.com/mods/stalker-anomaly/addons/screen-space-shaders
|
|
*/
|
|
|
|
uniform float4 ssfx_sss; // Dir Len, Omni Len, Grass Shadows, -
|
|
|
|
#include "screenspace_common.h"
|
|
#include "settings_screenspace_SSS.h"
|
|
|
|
Texture2D s_hud_mask;
|
|
|
|
float SSFX_ScreenSpaceShadows(float4 P, float3 N, float2 tc, float HudMask, uint iSample)
|
|
{
|
|
// Weapon Mask
|
|
bool IsHUD = HudMask <= 0;
|
|
|
|
float pLen = length(P.xyz);
|
|
|
|
// Distance Factor
|
|
float DFactor = saturate((pLen - 80) * 0.01f);
|
|
|
|
// Adjust Settings for weapons and scene.
|
|
float ray_detail = lerp(G_SSS_DETAIL, 0.05f, pLen * 0.02f);
|
|
float ray_thick = lerp(0.2f, 10, DFactor);
|
|
float ray_len = lerp(1.0, 20, DFactor);
|
|
|
|
ray_len *= saturate(P.z); // Limit the ray_len to avoid issues when surfaces are extremely close
|
|
|
|
if (IsHUD)
|
|
{
|
|
ray_detail = 0;
|
|
ray_len = G_SSS_WEAPON_LENGTH;
|
|
ray_thick = 1.0f;
|
|
}
|
|
|
|
RayTrace sss_ray = SSFX_ray_init(P, -L_sun_dir_e, ray_len * ssfx_sss.x, SSFX_SSS_DIR_QUALITY, hash12(tc * 100 + timers.xx * 100));
|
|
|
|
[unroll (SSFX_SSS_DIR_QUALITY)]
|
|
for (int i = 0; i < SSFX_SSS_DIR_QUALITY; 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
|
|
if (depth_ray.y <= SKY_EPS)
|
|
return 1;
|
|
|
|
// Disable weapons at some point to avoid wrong shadows on the ground
|
|
if (!IsHUD)
|
|
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)
|
|
return saturate(1.0f - G_SSS_INTENSITY);
|
|
|
|
// Step the ray + Noise
|
|
sss_ray.r_pos += sss_ray.r_step * (1.0f + hash12((tc * 100) + timers.xx * 100));
|
|
}
|
|
|
|
// None
|
|
return 1;
|
|
}
|
|
|
|
|
|
|
|
float SSFX_ScreenSpaceShadows_Point(float4 P, float2 tc, float3 LightPos, float HudMask, uint iSample)
|
|
{
|
|
// Light vector
|
|
float3 L_dir = -normalize(P.xyz - LightPos);
|
|
|
|
// Material conditions...
|
|
bool mat_flora = abs(P.w - MAT_FLORA) <= 0.04f;
|
|
|
|
// Weapon Mask
|
|
bool IsHUD = HudMask <= 0;
|
|
|
|
// Adjust Settings for weapons and scene.
|
|
float ray_detail = G_SSS_DETAIL;
|
|
float ray_thick = 0.2f;
|
|
float ray_len = 0.5f;
|
|
|
|
// Grass overwrite.
|
|
if (IsHUD)
|
|
{
|
|
ray_thick = 1.0f;
|
|
ray_len = 0.06f;
|
|
}
|
|
else
|
|
{
|
|
if (mat_flora)
|
|
{
|
|
ray_thick = 10.0f;
|
|
ray_len = 0.5f;
|
|
}
|
|
}
|
|
|
|
RayTrace sss_ray = SSFX_ray_init(P, L_dir, ray_len * ssfx_sss.y, SSFX_SSS_OMNI_QUALITY, hash12(tc * 100 + timers.xx * 100));
|
|
|
|
[unroll (SSFX_SSS_OMNI_QUALITY)]
|
|
for (int i = 0; i < SSFX_SSS_OMNI_QUALITY; 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
|
|
if (depth_ray.y <= SKY_EPS)
|
|
return 1;
|
|
|
|
// Disable weapons at some point to avoid wrong shadows on the ground
|
|
if (!IsHUD)
|
|
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)
|
|
return 1.0f - saturate(G_SSS_INTENSITY - smoothstep( SSFX_SSS_OMNI_QUALITY * 0.5f, SSFX_SSS_OMNI_QUALITY + 1, i));
|
|
|
|
// Step the ray
|
|
sss_ray.r_pos += sss_ray.r_step * (1.0f + hash12((tc * 100) + timers.xx * 100));
|
|
}
|
|
|
|
return 1;
|
|
} |