Files

88 lines
5.2 KiB
HLSL

#ifndef EXPHEIGHTFOG_BASE
#define EXPHEIGHTFOG_BASE
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
#if defined(_SG_EXPFOG)
float4 _SG_ExpFogParams;
float4 _SG_ExpFogParams2;
float4 _SG_ExpFogParams3;
float4 _SG_ExpFogDirInscatteringCol;
float4 _SG_ExpFogLightDir;
float4 _SG_ExpFogColParams;
#define CUSTOM_FOG_COORDS(ID) float4 _fogCoord : TEXCOORD##ID;
#define CUSTOM_TRANSFER_FOG(v2f, vertex) v2f##._fogCoord = GetExponentialHeightFog(GetCameraPositionWS() - GetVertexPositionInputs(vertex.xyz).positionWS)
#define CUSTOM_APPLY_FOG(v2f, pixelColor, lerpVal) pixelColor = lerp(pixelColor, pixelColor.rgb * v2f._fogCoord.a + v2f._fogCoord.rgb, saturate(lerpVal / _SG_ExpFogParams3.w))
// UE 4.22 HeightFogCommon.ush
// Calculate the line integral of the ray from the camera to the receiver position through the fog density function
// The exponential fog density function is d = GlobalDensity * exp(-HeightFalloff * y)
inline float CalculateLineIntegralShared(float FogHeightFalloff, float RayDirectionY, float RayOriginTerms)
{
float Falloff = max(-127.0f, FogHeightFalloff * RayDirectionY); // if it's lower than -127.0, then exp2() goes crazy in OpenGL's GLSL.
float LineIntegral = (1.0f - exp2(-Falloff)) / Falloff;
return RayOriginTerms * LineIntegral;
}
// UE 4.22 HeightFogCommon.ush
// @param WorldPositionRelativeToCamera = WorldPosition - InCameraPosition
inline float4 GetExponentialHeightFog(float3 WorldPositionRelativeToCamera) // camera to vertex
{
float MinFogOpacity = _SG_ExpFogColParams.w;
// Receiver
float3 CameraToReceiver = -WorldPositionRelativeToCamera;
float CameraToReceiverLengthSqr = dot(CameraToReceiver, CameraToReceiver);
float CameraToReceiverLengthInv = rsqrt(CameraToReceiverLengthSqr);
float CameraToReceiverLength = CameraToReceiverLengthSqr * CameraToReceiverLengthInv;
float3 CameraToReceiverNormalized = CameraToReceiver * CameraToReceiverLengthInv;
float RayOriginTerms = _SG_ExpFogParams.x;
float RayLength = CameraToReceiverLength;
float RayDirectionY = CameraToReceiver.y;
// Factor in StartDistance
float ExcludeDistance = _SG_ExpFogParams.w;
float ExcludeIntersectionTime = ExcludeDistance * CameraToReceiverLengthInv;
float CameraToExclusionIntersectionY = ExcludeIntersectionTime * CameraToReceiver.y;
float ExclusionIntersectionY = GetCameraPositionWS().y + CameraToExclusionIntersectionY;
float ExclusionIntersectionToReceiverY = CameraToReceiver.y - CameraToExclusionIntersectionY;
float Exponent = max(-127.0f, _SG_ExpFogParams.y * (ExclusionIntersectionY - (GetCameraPositionWS().y + _SG_ExpFogParams3.y)));
RayLength = (1.0f - ExcludeIntersectionTime) * CameraToReceiverLength;
RayDirectionY = ExclusionIntersectionToReceiverY;
RayOriginTerms = _SG_ExpFogParams3.x * exp2(-Exponent);
float ExponentialHeightLineIntegralShared = CalculateLineIntegralShared(_SG_ExpFogParams.y, RayDirectionY, RayOriginTerms);
float ExponentialHeightLineIntegral = ExponentialHeightLineIntegralShared * RayLength;
float3 InscatteringColor = _SG_ExpFogColParams.xyz;
float3 DirectionalInscattering = 0;
float DirectionalInscatteringStartDistance = _SG_ExpFogLightDir.w;
// Setup a cosine lobe around the light direction to approximate inscattering from the directional light off of the ambient haze;
float3 DirectionalLightInscattering = _SG_ExpFogDirInscatteringCol.xyz * pow(saturate(dot(CameraToReceiverNormalized, _SG_ExpFogLightDir.xyz)), _SG_ExpFogDirInscatteringCol.w);
// Calculate the line integral of the eye ray through the haze, using a special starting distance to limit the inscattering to the distance
float DirExponentialHeightLineIntegral = ExponentialHeightLineIntegralShared * max(RayLength - DirectionalInscatteringStartDistance, 0.0f);
// Calculate the amount of light that made it through the fog using the transmission equation
float DirectionalInscatteringFogFactor = saturate(exp2(-DirExponentialHeightLineIntegral));
// Final inscattering from the light
DirectionalInscattering = DirectionalLightInscattering * (1 - DirectionalInscatteringFogFactor);
// Calculate the amount of light that made it through the fog using the transmission equation
float ExpFogFactor = max(saturate(exp2(-ExponentialHeightLineIntegral)), MinFogOpacity);
float3 FogColor = (InscatteringColor) * (1 - ExpFogFactor) + DirectionalInscattering;
return float4(FogColor, ExpFogFactor);
}
inline float3 ApplyFogUnrealExp2Fog(float3 finalColor, float3 worldPos)
{
float4 fogCoord = GetExponentialHeightFog(worldPos.xyz - GetCameraPositionWS().xyz);
float lerpVal = distance(GetCameraPositionWS().xyz, worldPos.xyz);
return lerp(finalColor, finalColor * fogCoord.a + fogCoord.rgb, saturate(lerpVal / _SG_ExpFogParams3.w));
}
inline float3 ApplyFogUnrealExp2FogWithOffset(float3 finalColor, float3 worldPos, float fogFactor)
{
float4 fogCoord = GetExponentialHeightFog(worldPos.xyz - GetCameraPositionWS().xyz);
float lerpVal = distance(GetCameraPositionWS().xyz, worldPos.xyz);
return lerp(finalColor, finalColor * fogCoord.a + fogCoord.rgb, saturate(lerpVal / _SG_ExpFogParams3.w) * fogFactor);
}
#endif
#endif