e4s-game/gamedata/shaders/d3d11/reflections.hlsli
2026-06-18 01:18:29 +03:00

279 lines
7.3 KiB
HLSL

#ifndef reflections_h_2134124_inc
#define reflections_h_2134124_inc
// Screen Space Sky Reflections off
#define SKYBLED_FADE
#define USE_BASE_HUD_REFLECTIONS
#define USE_VASYAN_CUTOFF
// #define VSLR_SLOW_BREAK
// #define SSLR_SLOW_BREAK
uniform float4 scaled_screen_res;
float get_depth_fast(float2 tc)
{
float P = s_position.SampleLevel(smp_rtlinear, tc, 0).x;
return depth_unpack.x * rcp(P - depth_unpack.y);
}
float3 gbuf_unpack_position(float2 uv)
{
float depth = get_depth_fast(uv);
uv = uv * 2.0f - 1.0f;
return float3(uv * pos_decompression_params.xy, 1.0f) * depth;
}
float3 gbuf_unpack_position(float2 uv, float depth)
{
uv = uv * 2.0f - 1.0f;
return float3(uv * pos_decompression_params.xy, 1.0f) * depth;
}
float2 gbuf_unpack_uv(float3 position)
{
position.xy *= rcp(pos_decompression_params.xy * position.z);
return saturate(position.xy * 0.5 + 0.5);
}
#define SSLR_STEPS 30
#define MAX_FIND_STEP 5
float BinaryRefinement(inout float3 EndProj, float3 Reflect)
{
float HitDepth = 0.0f;
[unroll(MAX_FIND_STEP)]
for(int i = 0; i < MAX_FIND_STEP; ++i)
{
HitDepth = s_env.SampleLevel(smp_nofilter, EndProj.xyz, 0).w;
HitDepth *= HitDepth;
Reflect *= 0.5f;
EndProj += dot(EndProj, EndProj) > HitDepth ? -Reflect : Reflect;
}
HitDepth = s_env.SampleLevel(smp_nofilter, EndProj.xyz, 0).w;
HitDepth *= HitDepth;
return HitDepth;
}
float BinaryRefinementHUD(inout float3 EndProj, float3 Reflect)
{
float HitDepth = 0.0f;
[unroll(MAX_FIND_STEP)]
for(int i = 0; i < MAX_FIND_STEP; ++i)
{
HitDepth = s_position.SampleLevel(smp_nofilter, EndProj.xy, 0).x;
Reflect *= 0.5f;
EndProj += EndProj.z > HitDepth ? -Reflect : Reflect;
}
HitDepth = s_position.SampleLevel(smp_nofilter, EndProj.xy, 0).x;
return HitDepth;
}
float4 FastViewReflections(float3 Point, float3 Reflect)
{
float3 SamplePoint = Reflect;
float SampleHitPointLen = 0;
float Step = rcp(SSLR_STEPS + 1) * 0.01f;
float L = 0.011f;
float RadiusS = fog_params.z * fog_params.z;
float DistanceS = dot(Point, Point);
float DirectionS = dot(Reflect, Reflect);
if(DistanceS >= RadiusS) {
return float4(SamplePoint, 0.0f);
}
Step *= fog_params.z - length(Point); //sqrt((RadiusS - DistanceS) * rcp(DirectionS));
float Fade = 0;
float Delta = 0.0f;
[loop]
for(uint i = 0; i < SSLR_STEPS; ++i)
{
float JStep = Step * lerp(0.8f, 1.2f, Hash(dot(sin(SamplePoint.xyz * timers.x), float3(12.989, 42.364, 78.233))));
L += JStep;
Step *= 1.25f;
SamplePoint.xyz = Point.xyz + Reflect * L;
SampleHitPointLen = s_env.SampleLevel(smp_nofilter, SamplePoint.xyz, 0).w;
SampleHitPointLen *= SampleHitPointLen;
Delta = dot(SamplePoint, SamplePoint) - SampleHitPointLen;
if (Delta > 0 /*&& Delta <= JStep * 0.8f*/)
{
float3 JReflect = Reflect * JStep * 0.5f;
SamplePoint.xyz -= JReflect;
SampleHitPointLen = BinaryRefinement(SamplePoint.xyz, JReflect);
Delta = dot(SamplePoint.xyz, SamplePoint.xyz) - SampleHitPointLen;
Fade = abs(Delta) / max(dot(SamplePoint.xyz, SamplePoint.xyz), SampleHitPointLen) < 0.1f;
#ifdef VSLR_SLOW_BREAK
if(Fade)
#endif
break;
}
}
SamplePoint = normalize(SamplePoint) * sqrt(SampleHitPointLen);
return float4(SamplePoint, Fade);
}
float4 FastViewReflectionsSSR(float3 Point, float3 Reflect, bool is_hud)
{
float4 StartProj, EndProj;
float3 ReflectBase = Reflect;
float Step = rcp(SSLR_STEPS + 1);
bool Fade = false;
if(is_hud) {
StartProj = mul(m_P_hud, float4(Point, 1.0f)); StartProj.xyz /= StartProj.w;
EndProj = mul(m_P_hud, float4(Point + Reflect * Point.z, 1.0f)); EndProj.xyz /= EndProj.w;
StartProj.z *= 0.02f;
EndProj.z *= 0.02f;
} else {
StartProj = mul(m_P, float4(Point, 1.0f)); StartProj.xyz /= StartProj.w;
EndProj = mul(m_P, float4(Point + Reflect * Point.z, 1.0f)); EndProj.xyz /= EndProj.w;
}
Reflect = EndProj.xyz - StartProj.xyz;
StartProj.xy = StartProj.xy * float2(0.5f, -0.5f) + 0.5f;
Reflect.xy = Reflect.xy * float2(0.5f, -0.5f);
Reflect.xyz = normalize(Reflect.xyz);
Step *= GetMaxDirLength(StartProj.xyz, rcp(Reflect));
float L = 0.001f;
Step *= is_hud ? 0.2f : 1.0f;
float StepScale = is_hud ? 1.095f : 1.0f;
[loop]
for(uint i = 0; i < SSLR_STEPS; ++i)
{
float JStep = Step * lerp(0.8f, 1.2f, Hash(dot(sin(EndProj.xyz * timers.x), float3(12.989, 42.364, 78.233))));
L += JStep;
Step *= StepScale;
EndProj.xyz = StartProj.xyz + Reflect * L;
float HitDepth = s_position.SampleLevel(smp_nofilter, EndProj.xy, 0).x;
float Delta = EndProj.z - HitDepth;
if (Delta > 0 && (is_hud || HitDepth > 0.02f))
{
float3 JReflect = Reflect * JStep * 0.5f;
EndProj.xyz -= JReflect;
HitDepth = BinaryRefinementHUD(EndProj.xyz, JReflect);
float2 depthL = rcp(max(1.0f - HitDepth, 0.00001f));
float2 depthR = rcp(max(1.0f - EndProj.z, 0.00001f));
EndProj.z = HitDepth;
Fade = is_hud || abs(depthL - depthR) * rcp(max(depthL, depthR)) < 0.01f;
#ifdef SSLR_SLOW_BREAK
if(Fade)
#endif
break;
}
}
if(is_hud) {
Fade = Fade && EndProj.z < 0.02f;
#ifdef USE_BASE_HUD_REFLECTIONS
if(!Fade && ReflectBase.z > 0.0f) {
EndProj = mul(m_P, float4(ReflectBase, 1.0f)); EndProj.xyz /= EndProj.w;
EndProj.xy = EndProj.xy * float2(0.5f, -0.5f) + 0.5f;
EndProj.xy = saturate(EndProj.xy);
EndProj.z = s_position.SampleLevel(smp_nofilter, EndProj.xy, 0).x;
Fade = GetBorderAtten(EndProj.xy, 0.001f) > 0.0f;
Fade = Fade && EndProj.z > 0.02f && EndProj.z < 1.0f;
EndProj.z *= 0.0002f;
}
#endif
} else {
Fade = Fade && EndProj.z < 1.0f && EndProj.z > 0.02f;
}
float3 ReflPoint = GbufferGetPointRealUnjitter(EndProj.xy, EndProj.z);
return float4(ReflPoint, Fade);
}
float4 ScreenSpaceLocalReflections(float3 Point, float3 Reflect)
{
float2 ReflUV = 0.0;
float3 HitPos, TestPos;
float L = 0.025f, DeltaL = 0.0f;
float Fade = saturate(dot(Reflect, normalize(Point)) * 4.0f);
if (Fade < 0.001f)
{
return 0.0f;
}
[unroll(15)]
for (int i = 0; i < 15; i++)
{
TestPos = Point + Reflect * L;
ReflUV = gbuf_unpack_uv(TestPos);
HitPos = gbuf_unpack_position(ReflUV);
if (all(min(min(1.f - ReflUV.x, ReflUV.x), min(1.f - ReflUV.y, ReflUV.y))))
{
L = length(Point - HitPos);
}
else
{
return 0.0f;
}
}
DeltaL = length(HitPos) - length(Point);
Fade *= step(-0.4f, DeltaL);
float Attention = GetBorderAtten(ReflUV, 0.125f);
ReflUV -= s_velocity.SampleLevel(smp_rtlinear, ReflUV, 0).xy * float2(0.5f, -0.5f);
Fade *= min(Attention, GetBorderAtten(ReflUV, 0.125f));
#ifdef SKYBLED_FADE
float Fog = saturate(length(HitPos) * fog_params.w + fog_params.x);
Fade *= 1.f - Fog * Fog;
#endif
float3 Color = s_image.SampleLevel(smp_rtlinear, ReflUV, 0).xyz;
return float4(Color, Fade);
}
float4 calc_reflections(float2 pos2d, float zpos, float3 vreflect)
{
float3 Point = zpos * float3(pos2d * pos_decompression_params.zw - pos_decompression_params.xy, 1.0f);
return ScreenSpaceLocalReflections(Point, mul((float3x3)m_V, vreflect));
}
#endif