#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