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

106 lines
4.0 KiB
HLSL

// Copyright Epic Games, Inc. All Rights Reserved.
/*=============================================================================
VolumetricFogLightFunction.usf
=============================================================================*/
#include "Common.ush"
#include "/Engine/Generated/Material.ush"
#include "LightFunctionCommon.ush"
float4x4 ShadowToTranslatedWorld;
/** Fade distance in x, disabled brightness in y, output for preview shadows mask in z. */
float3 LightFunctionParameters2;
float3 LightTranslatedWorldPosition;
float2 LightFunctionTexelSize;
void Main(
in noperspective float4 UV : TEXCOORD0,
in FStereoPSInput StereoInput,
in float4 SvPosition : SV_Position,
out float4 OutColor : SV_Target0
)
{
ResolvedView = ResolveView();
float4 TranslatedWorldPosition = float4(0,0,0,0);
float3 LightVector = float3(0,0,0);
float Depth = 0.000001f;
float2 ScreenPosition = 0.0f;
#if LIGHT_TYPE == 0 // Point light
float Theta = (UV.x * (2*PI)) - PI;
float Phi = UV.y * PI;
float X = cos(Theta) * sin(Phi);
float Y = sin(Theta) * sin(Phi);
float Z = cos(Phi);
LightVector = float3(Z, Y, X);
TranslatedWorldPosition = float4(LightTranslatedWorldPosition + LightVector.zyx, 1);
#elif LIGHT_TYPE == 1 // Spot light
ScreenPosition = (SvPosition.xy * LightFunctionTexelSize);
ScreenPosition.x = 1 - ScreenPosition.x;
ScreenPosition.y = 1 - ScreenPosition.y;
// Wrap ScreenPosition to within the atlas tile
ScreenPosition = frac(ScreenPosition);
// Compute translated world position (inverse shadow projection) from the screen position
// make SvPosition appear to be rasterized with the depth from the depth buffer
TranslatedWorldPosition = mul(float4(ScreenPosition, Depth, 1), ShadowToTranslatedWorld);
TranslatedWorldPosition.xyz /= TranslatedWorldPosition.w;
// Compute the light vector containing UV from the translated world position
float4 Hom = mul(float4(TranslatedWorldPosition.xyz, 1), LightFunctionTranslatedWorldToLight);
LightVector = Hom.xyz / Hom.w;
#elif LIGHT_TYPE == 2 // Rect light
ScreenPosition = (SvPosition.xy * LightFunctionTexelSize - float2(0.5f, 0.5f)) * float2(2, 2);
ScreenPosition.xy = frac(ScreenPosition.xy);
// Compute translated world position (inverse shadow projection) from the screen position
// make SvPosition appear to be rasterized with the depth from the depth buffer
TranslatedWorldPosition = mul(float4(ScreenPosition, Depth, 1), ShadowToTranslatedWorld);
TranslatedWorldPosition.xyz /= TranslatedWorldPosition.w;
// Compute the light vector containing UV from the translated world position
float4 Hom = mul(float4(TranslatedWorldPosition.xyz, 1), LightFunctionTranslatedWorldToLight);
LightVector = Hom.xyz / Hom.w;
LightVector.xyz = LightVector.zyx; // Swap to match UV convention
#else //LIGHT_TYPE == 3 // Directional light
// Directional light
ScreenPosition = (SvPosition.xy * LightFunctionTexelSize - float2(0.5f, 0.5f)) * float2(2, -2);
// make SvPosition appear to be rasterized with the depth from the depth buffer
TranslatedWorldPosition = mul(float4(ScreenPosition, Depth, 1), ShadowToTranslatedWorld);
TranslatedWorldPosition.xyz /= TranslatedWorldPosition.w;
float4 Hom = mul(float4(TranslatedWorldPosition.xyz, 1), LightFunctionTranslatedWorldToLight);
LightVector = Hom.xyz / Hom.w;
#endif
float3 LightFunction = GetLightFunctionColor(LightVector, TranslatedWorldPosition.xyz);
float GreyScale = dot(LightFunction, .3333f).x;
// Calculate radial view distance for stable fading
float ViewDistance = GetDistanceToCameraFromViewVector(PrimaryView.TranslatedWorldCameraOrigin - TranslatedWorldPosition.xyz);
float DistanceFadeAlpha = saturate((LightFunctionParameters2.x - ViewDistance) / (LightFunctionParameters2.x * .2f));
// Fade to disabled based on LightFunctionFadeDistance
GreyScale = lerp(LightFunctionParameters2.y, GreyScale, DistanceFadeAlpha);
// Fade to disabled based on ShadowFadeFraction
GreyScale = lerp(LightFunctionParameters2.y, GreyScale, LightFunctionParameters.y);
OutColor = GreyScale;
}