Files
UnrealEngine/Engine/Shaders/Private/SkyLightingDiffuseShared.ush
2025-05-18 13:04:45 +08:00

140 lines
5.1 KiB
HLSL

// Copyright Epic Games, Inc. All Rights Reserved.
/*=============================================================================
SkyLightingDiffuseShared.usf
=============================================================================*/
#pragma once
#include "SkyLightingShared.ush"
#include "ClearCoatCommon.ush"
#include "ShadingEnergyConservation.ush"
#include "HairBsdf.ush"
#include "HairStrands/HairStrandsEnvironmentLightingCommon.ush"
#ifndef APPLY_SKY_SHADOWING
#define APPLY_SKY_SHADOWING 0
#endif
float3 ContrastAndNormalizeMulAdd;
float OcclusionExponent;
float OcclusionCombineMode;
// The following paramaters are declared in SkyLightingShared.usf
// float4 OcclusionTintAndMinOcclusion;
struct FSkyLightVisibilityData
{
float SkyDiffuseLookUpMul;
float3 SkyDiffuseLookUpAdd;
float3 SkyDiffuseLookUpNormal;
};
FSkyLightVisibilityData GetSkyLightVisibilityData(float3 SkyLightingNormal, const float3 WorldNormal, const float GBufferAO, float ScreenAO, const float3 BentNormal)
{
float SkyVisibility = 1;
float DotProductFactor = 1;
#if APPLY_SKY_SHADOWING
#define USE_DIRECTIONAL_OCCLUSION_ON_SKY_DIFFUSE 1
#if USE_DIRECTIONAL_OCCLUSION_ON_SKY_DIFFUSE
{
SkyVisibility = length(BentNormal);
float3 NormalizedBentNormal = BentNormal / (max(SkyVisibility, .00001f));
// Use more bent normal in corners
float BentNormalWeightFactor = SkyVisibility;
SkyLightingNormal = lerp(NormalizedBentNormal, WorldNormal, BentNormalWeightFactor);
DotProductFactor = lerp(dot(NormalizedBentNormal, WorldNormal), 1, BentNormalWeightFactor);
}
#else
{
SkyVisibility = length(BentNormal);
}
#endif
float ContrastCurve = 1 / (1 + exp(-ContrastAndNormalizeMulAdd.x * (SkyVisibility * 10 - 5)));
SkyVisibility = saturate(ContrastCurve * ContrastAndNormalizeMulAdd.y + ContrastAndNormalizeMulAdd.z);
// Apply DFAO controls
SkyVisibility = pow(SkyVisibility, OcclusionExponent);
SkyVisibility = lerp(SkyVisibility, 1, OcclusionTintAndMinOcclusion.w);
#endif
// Combine with other AO sources
if (OcclusionCombineMode == 0)
{
// Combine with min which nicely avoids over-occlusion in cases where strong DFAO is present along with strong SSAO (distant trees)
SkyVisibility = min(SkyVisibility, min(GBufferAO, ScreenAO));
}
else
{
// Combine with mul, which continues to add SSAO depth even indoors. SSAO will need to be tweaked to be less strong.
SkyVisibility = SkyVisibility * min(GBufferAO, ScreenAO);
}
// Apply AO to the sky diffuse and account for darkening due to the geometry term
// apply the Diffuse color to the lighting (including OcclusionTintAndMinOcclusion as it's considered another light, that fixes SubsurfaceProfile being too dark)
FSkyLightVisibilityData SkyVisData;
SkyVisData.SkyDiffuseLookUpMul = SkyVisibility * DotProductFactor;
SkyVisData.SkyDiffuseLookUpAdd = (1 - SkyVisibility) * OcclusionTintAndMinOcclusion.xyz;
SkyVisData.SkyDiffuseLookUpNormal = SkyLightingNormal;
return SkyVisData;
}
float3 SkyLightDiffuse(FGBufferData GBuffer, float AmbientOcclusion, float2 BufferUV, float2 ScreenPosition, float3 BentNormal, float3 DiffuseColor)
{
float2 UV = BufferUV;
float3 Lighting = 0;
float3 SkyLightingNormal = GetClearCoatBottomNormal(GBuffer, GBuffer.WorldNormal);
FSkyLightVisibilityData SkyVisData = GetSkyLightVisibilityData(SkyLightingNormal, GBuffer.WorldNormal, GBuffer.GBufferAO, AmbientOcclusion, BentNormal);
const float3 N = GBuffer.WorldNormal;
const float3 V = -normalize(mul(float3(ScreenPosition, 1), DFToFloat3x3(PrimaryView.ScreenToWorld)).xyz);
const float NoV = saturate(dot(V, N));
const FBxDFEnergyTerms EnergyTerms = ComputeGGXSpecEnergyTerms(GBuffer.Roughness, NoV, GBuffer.SpecularColor);
float3 DiffuseWeight = ComputeEnergyPreservation(EnergyTerms);
BRANCH
if (GBuffer.ShadingModelID == SHADINGMODELID_TWOSIDED_FOLIAGE)
{
float3 SubsurfaceLookup = GetSkySHDiffuse(-GBuffer.WorldNormal) * View.SkyLightColor.rgb;
float3 SubsurfaceColor = ExtractSubsurfaceColor(GBuffer);
Lighting += SkyVisData.SkyDiffuseLookUpMul * SubsurfaceLookup * SubsurfaceColor;
}
if (GBuffer.ShadingModelID == SHADINGMODELID_SUBSURFACE || GBuffer.ShadingModelID == SHADINGMODELID_PREINTEGRATED_SKIN)
{
float3 SubsurfaceColor = ExtractSubsurfaceColor(GBuffer);
// Add subsurface energy to diffuse
DiffuseColor += SubsurfaceColor;
}
BRANCH
if (GBuffer.ShadingModelID == SHADINGMODELID_HAIR)
{
float3 L = 0;
DiffuseColor = EvaluateEnvHair(GBuffer, V, N, L /*out*/);
DiffuseWeight = 1.0f;
SkyVisData.SkyDiffuseLookUpNormal = L;
}
if (GBuffer.ShadingModelID == SHADINGMODELID_CLOTH)
{
float3 ClothFuzz = ExtractSubsurfaceColor(GBuffer);
DiffuseColor += ClothFuzz * GBuffer.CustomData.a;
}
// Compute the preconvolved incoming lighting with the bent normal direction
float3 DiffuseLookup = GetSkySHDiffuse(SkyVisData.SkyDiffuseLookUpNormal) * View.SkyLightColor.rgb;
// And accumulate the lighting
Lighting += (SkyVisData.SkyDiffuseLookUpMul * DiffuseLookup + SkyVisData.SkyDiffuseLookUpAdd) * DiffuseColor * DiffuseWeight;
Lighting *= View.PreExposure;
//Lighting = (Texture2DSampleLevel(BentNormalAOTexture, BentNormalAOSampler, UV, 0).xyz);
return Lighting;
}