#ifndef screenspacecontactshadows_hlsl_included #define screenspacecontactshadows_hlsl_included #ifndef HUD_SHADOWS_STEPS #define HUD_SHADOWS_STEPS 35 #endif #ifndef HUD_SHADOWS_TRACE_LEN #define HUD_SHADOWS_TRACE_LEN 0.07f #endif float SampleHudHitPoint(float2 TexCoord) { float depth = s_position.SampleLevel(smp_nofilter, TexCoord, 0).x; return depth_unpack.z * rcp(min(1.0f, depth * 50.0f) - depth_unpack.w); } float2 GetPointTexCoord(float3 Point) { Point.xy *= rcp(pos_decompression_params_hud.xy * Point.z); return saturate(Point.xy * 0.5f + 0.5f); } void RayTraceContactShadow(float2 TexCoord, float3 Point, float3 LightDir, inout float3 Light) { Point.xyz *= 0.99f; LightDir *= min(Point.z, HUD_SHADOWS_TRACE_LEN); float4 StartProj = mul(m_P_hud, float4(Point, 1.0f)); StartProj.xyz /= StartProj.w; float4 EndProj = mul(m_P_hud, float4(Point - LightDir, 1.0f)); EndProj.xyz /= EndProj.w; StartProj.xy = StartProj.xy * float2(0.5f, -0.5f) + 0.5f; StartProj.z *= 0.02f; EndProj.xy = EndProj.xy * float2(0.5f, -0.5f) + 0.5f; EndProj.z *= 0.02f; LightDir = EndProj.xyz - StartProj.xyz; StartProj.xy = TexCoord.xy; float Len = GetMaxDirLength(StartProj.xyz, rcp(LightDir)); LightDir *= min(1.0f, Len); LightDir *= rcp(HUD_SHADOWS_STEPS); float ContactShadow = 0.0f; [unroll(HUD_SHADOWS_STEPS)] for (int i = 0; i < HUD_SHADOWS_STEPS; ++i) { StartProj.xyz += LightDir * float(0.8f + 0.4f * Hash(StartProj.xyz)); float HitDepth = s_position.SampleLevel(smp_nofilter, StartProj.xy, 0).x; if (HitDepth <= StartProj.z) { ContactShadow += 0.2f; if (ContactShadow >= 1.0f) { ContactShadow = 1.0f; break; } } } ContactShadow *= GetBorderAtten(StartProj.xy, 0.0125f); Light *= 1.0f - saturate(ContactShadow); } #endif