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

172 lines
5.3 KiB
HLSL

#ifndef metalic_roughness_ambient_h_ixray_included
#define metalic_roughness_ambient_h_ixray_included
#include "common.hlsli"
//fitted for height-correlated smith
float2 EpicGamesEnvBRDFApprox(float NdotV, float roughness)
{
//clamped cuz of extreme spike
NdotV = min(NdotV, 0.998);
float nsqr = NdotV * NdotV;
float rsqr = roughness * roughness;
float4 fac = float4(0.0187, 1.0133, 1.0000, 1.0000) +
float4(1.9496, -2.4717, -0.0333, 2.0508) * NdotV +
float4(1.2265, -1.2172, -1.3097, 0.2342) * roughness +
float4(-7.6907, 3.4300, 0.5972, -26.9406) * NdotV * roughness +
float4(18.3314, 1.4794, 19.3537, 11.1429) * nsqr +
float4(-0.2894, 0.5564, 1.5052, 7.0828) * rsqr +
float4(-19.3056, -2.2456, -28.2302, 18.5470) * nsqr * roughness +
float4(7.0144, -1.8934, 1.3307, 50.6469) * NdotV * rsqr +
float4(1.5728, 1.3618, 15.2939, -63.3557) * nsqr * rsqr;
return saturate(fac.xy / fac.zw);
}
float3 CompureDiffuseIrradance(float3 N, float3 Hemi)
{
float3 LightDirection = mul((float3x3)m_invV, N).xyz;
#ifdef IBL_REMAP_IRRADANCE
RemapVector(LightDirection);
#endif
#ifdef USE_NORMAL_HEMI_DISTRIBUTION
Hemi = min(Hemi, LightDirection.yyy * 0.375f + 0.375f);
#endif
float3 SampleLast = env_s0.SampleLevel(smp_linear, LightDirection, 0.0f).xyz;
float3 SampleNext = env_s1.SampleLevel(smp_linear, LightDirection, 0.0f).xyz;
#ifdef USE_CGIM_SKY_TWEAK
float topToDownVec = saturate(LightDirection.y);
topToDownVec *= topToDownVec;
float Factor = SMALLSKY_TOP_VECTOR_POWER;
Factor = saturate(Factor + (1.0 - Factor) * topToDownVec) + (1.0 - Factor) * 0.5f;
Hemi *= Factor * Factor; float3 Irradance = 1.0f;
Hemi *= lerp(SampleLast, SampleNext, L_hemi_color.w);
#else
float3 Irradance = lerp(SampleLast, SampleNext, L_hemi_color.w);
#endif
#ifdef USE_DIFFUSE_SKY_COLOR
#ifdef USE_BGRA_SKYCOLOR
Irradance *= L_sky_color.zyx;
#else
Irradance *= L_sky_color.xyz;
#endif
#else
Irradance *= L_hemi_color.xyz;
#endif
#ifdef USE_LEGACY_LIGHT
Irradance *= Irradance;
#endif
return Irradance * Hemi;
}
float3 CompureSpecularIrradance(float3 R, float3 Hemi, float Roughness)
{
float3 LightDirection = mul((float3x3)m_invV, R);
#ifdef USE_OLD_VIEW_REFLECTIONS
R = mul(m_V_old, LightDirection);
#endif
#ifndef IBL_MAX_LOD
float4 MipLevels = 0.0f;
sky_s0.GetDimensions(MipLevels.x, MipLevels.y, MipLevels.z, MipLevels.w);
float2 Lod = MipLevels.w * Roughness;
#ifdef USE_HQ_SKY2_LOD
sky_s1.GetDimensions(MipLevels.x, MipLevels.y, MipLevels.z, MipLevels.w);
Lod.y = MipLevels.w * Roughness;
#endif
#else
float2 Lod = IBL_MAX_LOD * Roughness;
#endif
#ifdef IBL_FAKE_IRRADANCE
float3 SampleLastD = env_s0.SampleLevel(smp_rtlinear, LightDirection, 0.0f).xyz;
float3 SampleNextD = env_s1.SampleLevel(smp_rtlinear, LightDirection, 0.0f).xyz;
#endif
#ifdef IBL_REMAP_POSITIVE_Y
LightDirection.y = abs(LightDirection.y);
#endif
#ifdef IBL_REMAP_REFLECTIONS
RemapVector(LightDirection);
#endif
float3 SampleLast = sky_s0.SampleLevel(smp_linear, LightDirection, Lod.x).xyz;
float3 SampleNext = sky_s1.SampleLevel(smp_linear, LightDirection, Lod.y).xyz;
#ifdef IBL_FAKE_IRRADANCE
SampleLast = lerp(SampleLast, SampleLastD, Roughness);
SampleNext = lerp(SampleNext, SampleNextD, Roughness);
#endif
float3 Irradance = lerp(SampleLast, SampleNext, L_hemi_color.w);
#ifdef USE_SPECULAR_HEMI_COLOR
Irradance *= L_hemi_color.xyz;
#else
#ifdef USE_BGRA_SKYCOLOR
Irradance *= L_sky_color.zyx;
#else
Irradance *= L_sky_color.xyz;
#endif
#endif
#ifdef USE_VIEW_REFLECTIONS
float4 SampleRef = s_env.SampleLevel(smp_linear, R, 8.0f * Roughness);
SampleRef.xyz *= rcp(1.00001f - SampleRef.xyz);
float fog = saturate(SampleRef.w * fog_params.w + fog_params.x);
Irradance = lerp(PopGamma(SampleRef.xyz), Irradance, fog);
#endif
return Irradance * Hemi;
}
float3 AmbientLighting(float3 DiffuseIrradance, float3 SpecularIrradance, float NdotV, float3 Color, float Metalness, float Roughness, float3 F0 = 0.04f)
{
DiffuseIrradance = PushGamma(DiffuseIrradance);
SpecularIrradance = PushGamma(SpecularIrradance);
DiffuseIrradance *= (1.0f - Metalness) * Color;
float2 BRDF = EpicGamesEnvBRDFApprox(NdotV, Roughness);
float3 F = lerp(F0, Color, Metalness) * BRDF.x + BRDF.y;
return lerp(DiffuseIrradance, SpecularIrradance, F);
}
float3 AmbientLighting(float3 View, float3 Normal, float3 Color, float Metalness, float Roughness, float Hemi, float3 F0 = 0.04f)
{
float3 Reflect = reflect(View, Normal);
#ifndef USE_LEGACY_LIGHT
float3 DiffuseIrradance = CompureDiffuseIrradance(Normal, Hemi) + L_ambient.xyz;
float3 SpecularIrradance = CompureSpecularIrradance(Reflect, Hemi, Roughness);
float NdotV = max(0.0, dot(Normal, -View));
return AmbientLighting(DiffuseIrradance, SpecularIrradance, NdotV, Color, Metalness, Roughness, F0);
#else
float Specular = 0.5f - 0.5f * dot(View, Reflect);
float2 Material = s_material.SampleLevel(smp_material, float3(Hemi, Specular, Metalness), 0).xy;
float3 DiffuseIrradance = CompureDiffuseIrradance(Normal, Material.x) + L_ambient.xyz;
float3 SpecularIrradance = CompureDiffuseIrradance(Reflect, Material.y);
return DiffuseIrradance * Color + SpecularIrradance * Roughness;
#endif
}
#endif