158 lines
4.7 KiB
PostScript
158 lines
4.7 KiB
PostScript
|
/**
|
||
|
* @ Version: SCREEN SPACE SHADERS - UPDATE 18
|
||
|
* @ Description: Rain patch normal
|
||
|
* @ Modified time: 2023-10-09 07:25
|
||
|
* @ Author: https://www.moddb.com/members/ascii1457
|
||
|
* @ Mod: https://www.moddb.com/mods/stalker-anomaly/addons/screen-space-shaders
|
||
|
*/
|
||
|
|
||
|
#include "common.h"
|
||
|
#include "lmodel.h"
|
||
|
#include "shadow.h"
|
||
|
|
||
|
#include "screenspace_common_ripples.h"
|
||
|
|
||
|
uniform float4 ssfx_wetsurfaces_1; // Ripples [ Size, Speed, Min Speed, Int ]
|
||
|
uniform float4 ssfx_wetsurfaces_2; // FallWater [ Size, Speed, Min Speed, Int ]
|
||
|
|
||
|
Texture2D s_water;
|
||
|
Texture2D s_waterFall;
|
||
|
|
||
|
float4 RainFallof;
|
||
|
|
||
|
float3 GetWaterFall( Texture2D s_texture, float2 tc)
|
||
|
{
|
||
|
// 0.75 1.5 0.2 0.5
|
||
|
|
||
|
// Num of columns
|
||
|
float col_num = 50;
|
||
|
float col_scale = 1.0 / col_num;
|
||
|
|
||
|
// Original UV Coors
|
||
|
float2 tc_ori = tc * ssfx_wetsurfaces_2.x;
|
||
|
|
||
|
// UV Columns
|
||
|
float2 col_tc = float2(frac(tc_ori.x * col_num), tc_ori.y);
|
||
|
|
||
|
// Column ID to add a random offset and adjust horizontal offset
|
||
|
half col_id = ceil(tc_ori.x * col_num);
|
||
|
|
||
|
// Random Y-Offset for each column
|
||
|
float col_offset = hash22(float2(col_id, 1.0));
|
||
|
|
||
|
// Limit min speed
|
||
|
col_offset = (col_offset < ssfx_wetsurfaces_2.z ? col_offset * 3.0f : col_offset);
|
||
|
|
||
|
// Animate
|
||
|
col_offset += timers.x * col_offset * rain_params.x * ssfx_wetsurfaces_2.y;
|
||
|
|
||
|
// Add wabbly
|
||
|
//col_tc.x += sin((tc_ori.y + col_offset) * 20) * 0.5f + 0.5f;
|
||
|
|
||
|
// Base Bump. Columns UVs, scale and apply offset.
|
||
|
float3 water = s_texture.Sample(smp_base, (col_tc * float2(col_scale, 1.0f) + float2(col_scale * col_id, col_offset)));
|
||
|
|
||
|
// Bump to -1.0 ~ 1.0
|
||
|
water.xyz = water.xzy * 2.0f - 1.0f;
|
||
|
|
||
|
// Intensity
|
||
|
water.xyz *= ssfx_wetsurfaces_2.w;
|
||
|
|
||
|
return water.xyz;
|
||
|
}
|
||
|
|
||
|
#ifndef ISAMPLE
|
||
|
#define ISAMPLE 0
|
||
|
#endif
|
||
|
|
||
|
#ifdef MSAA_OPTIMIZATION
|
||
|
float4 main ( float2 tc : TEXCOORD0, float2 tcJ : TEXCOORD1, float4 Color : COLOR, float4 pos2d : SV_Position, uint iSample : SV_SAMPLEINDEX ) : SV_Target
|
||
|
#else
|
||
|
float4 main ( float2 tc : TEXCOORD0, float2 tcJ : TEXCOORD1, float4 Color : COLOR, float4 pos2d : SV_Position ) : SV_Target
|
||
|
#endif
|
||
|
{
|
||
|
|
||
|
#ifdef MSAA_OPTIMIZATION
|
||
|
gbuffer_data gbd = gbuffer_load_data( tc, pos2d, iSample );
|
||
|
#else
|
||
|
gbuffer_data gbd = gbuffer_load_data( tc, pos2d, ISAMPLE );
|
||
|
#endif
|
||
|
|
||
|
// Buffers
|
||
|
float4 _P = float4( gbd.P, 1.0 );
|
||
|
float3 _N = normalize(gbd.N.xyz);
|
||
|
float3 _D = gbd.C;
|
||
|
float _M = gbd.mtl;
|
||
|
|
||
|
float4 PS = mul( m_shadow, _P );
|
||
|
float3 WorldP = mul( m_sunmask, _P );
|
||
|
float3 WorldN = mul( m_sunmask, _N.xyz );
|
||
|
|
||
|
// Read rain projection with some jetter. Also adding pixel normal
|
||
|
// factor to jitter to make rain strips more realistic.
|
||
|
float Cover = shadow_rain( PS, WorldP.xz - WorldN.xz ); // Wet Surfaces fix by Diana.Petran
|
||
|
|
||
|
// Distance
|
||
|
float p_len = length( _P.xyz );
|
||
|
bool is_flora = abs(_M - 0.15) < 0.04f;
|
||
|
bool is_terrain = abs(_M - 0.95) < 0.04f;
|
||
|
|
||
|
// Rain parameters ( Wetness > 0.5 = 100% | Rain Intensity > 0.66 = 100% )
|
||
|
float Wetness = saturate(rain_params.y * 2.0f);
|
||
|
float RainInt = clamp(rain_params.x * ssfx_wetsurfaces_1.y, ssfx_wetsurfaces_1.z * (rain_params.x > 0), 2.0f); // 1.5
|
||
|
|
||
|
// [ BUMP ] -------------------------------------------
|
||
|
float3 waterSplash = 0;
|
||
|
waterSplash.xy = ssfx_rain_ripples( s_water, WorldP.xz * ssfx_wetsurfaces_1.x, float3(RainInt, ssfx_wetsurfaces_1.w, 6), _P.z); // 0.9
|
||
|
|
||
|
// Blending weights ( We don't want splashes or fall water on FLORA )
|
||
|
float3 weights = WorldN.xyz * !is_flora;
|
||
|
|
||
|
// Water Fall
|
||
|
float3 waterFallX = GetWaterFall( s_waterFall, WorldP.zy );
|
||
|
float3 waterFallZ = GetWaterFall( s_waterFall, WorldP.xy );
|
||
|
|
||
|
// Base bump - Splahes
|
||
|
float3 water = waterSplash * smoothstep(0.75f, 0.8f, weights.y);
|
||
|
|
||
|
// Adjust Water fall and add to the Normal
|
||
|
weights.xz = saturate(abs(weights.xz) - 0.15f);
|
||
|
|
||
|
weights.xz *= float2(weights.x > weights.z, weights.x < weights.z);
|
||
|
|
||
|
water += waterFallX.yxz * weights.x;
|
||
|
water += waterFallZ.zxy * weights.z;
|
||
|
|
||
|
// HUD attenuations ( Remove Terrain & Flora )
|
||
|
float HUD_Attenuation = smoothstep( 1.0f, 1.3f, p_len + (is_terrain * 1.3f) ) * !is_flora;
|
||
|
|
||
|
// Apply attenuations
|
||
|
water *= HUD_Attenuation * saturate(RainInt) * Cover;
|
||
|
|
||
|
// Convert normal to view space
|
||
|
water = mul( m_V, water );
|
||
|
|
||
|
// Add water normal
|
||
|
_N = normalize(_N + water.xyz);
|
||
|
|
||
|
|
||
|
// [ GLOSS ] ------------------------------------------
|
||
|
float Gloss = (0.15f + saturate(RainInt) * 0.05) * Wetness; // Wetness
|
||
|
|
||
|
// Fade to full cover. ( RainFallof.y = far shadow rain rendering )
|
||
|
Cover += smoothstep( RainFallof.y - 20, RainFallof.y, _P.z );
|
||
|
|
||
|
// If gloss is high, remove cover factor
|
||
|
Gloss *= HUD_Attenuation * saturate(Cover + (gbd.gloss > 0.3f));
|
||
|
|
||
|
// Limit gloss on terrain ( Puddles )
|
||
|
Gloss = (is_terrain && gbd.gloss > 0.3f) ? 0.15f : Gloss;
|
||
|
|
||
|
// Remove rain gloss from bottom surfaces
|
||
|
Gloss *= saturate(weights.y * 1.5f);
|
||
|
|
||
|
// Apply distance falloff
|
||
|
Gloss *= smoothstep( 250, 200, p_len );
|
||
|
|
||
|
return float4( _N.xyz, Gloss );
|
||
|
}
|