279 lines
7.3 KiB
HLSL
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
|
|
|