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

89 lines
5.0 KiB
HLSL

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#define SharedAmbientInnerSampler View.SharedBilinearClampedSampler
#define SharedAmbientOuterSampler View.SharedBilinearClampedSampler
#define SharedDirectionalInnerSampler View.SharedBilinearClampedSampler
#define SharedDirectionalOuterSampler View.SharedBilinearClampedSampler
void ComputeVolumeUVs(float3 TranslatedWorldPosition, float3 LightingPositionOffset, out float3 InnerVolumeUVs, out float3 OuterVolumeUVs, out float FinalLerpFactor)
{
// Apply an offset to the world position used for lighting, which breaks up artifacts from using a low res volume texture
InnerVolumeUVs = (TranslatedWorldPosition + LightingPositionOffset * View.TranslucencyLightingVolumeInvSize[0].w - View.TranslucencyLightingVolumeMin[0].xyz) * View.TranslucencyLightingVolumeInvSize[0].xyz;
OuterVolumeUVs = (TranslatedWorldPosition + LightingPositionOffset * View.TranslucencyLightingVolumeInvSize[1].w - View.TranslucencyLightingVolumeMin[1].xyz) * View.TranslucencyLightingVolumeInvSize[1].xyz;
// Controls how fast the lerp between the inner and outer cascades happens
// Larger values result in a shorter transition distance
float TransitionScale = 6;
// Setup a 3d lerp factor going to 0 at the edge of the inner volume
float3 LerpFactors = saturate((.5f - abs(InnerVolumeUVs - .5f)) * TransitionScale);
FinalLerpFactor = LerpFactors.x * LerpFactors.y * LerpFactors.z;
}
float4 GetAmbientLightingVectorFromTranslucentLightingVolume(float3 InnerVolumeUVs, float3 OuterVolumeUVs, float FinalLerpFactor)
{
// Lookup the inner and outer cascade ambient lighting values
float4 InnerLighting = Texture3DSampleLevel(TranslucencyLightingVolumeAmbientInner, SharedAmbientInnerSampler, InnerVolumeUVs, 0);
float4 OuterLighting = Texture3DSampleLevel(TranslucencyLightingVolumeAmbientOuter, SharedAmbientOuterSampler, OuterVolumeUVs, 0);
// Lerp between cascades
return lerp(OuterLighting, InnerLighting, FinalLerpFactor);
}
float3 GetDirectionalLightingVectorFromTranslucentLightingVolume(float3 InnerVolumeUVs, float3 OuterVolumeUVs, float FinalLerpFactor)
{
// Fetch both the ambient and directional values for both cascades
float3 InnerVector1 = Texture3DSampleLevel(TranslucencyLightingVolumeDirectionalInner, SharedDirectionalInnerSampler, InnerVolumeUVs, 0).rgb;
float3 OuterVector1 = Texture3DSampleLevel(TranslucencyLightingVolumeDirectionalOuter, SharedDirectionalOuterSampler, OuterVolumeUVs, 0).rgb;
// Lerp between cascades
return lerp(OuterVector1, InnerVector1, FinalLerpFactor);
}
#include "SHCommon.ush"
void GetVolumeLightingNonDirectional(float4 AmbientLightingVector, float3 DiffuseColor, inout float3 InterpolatedLighting, out float4 VolumeLighting)
{
// Normal is not taken into account with non directional lighting, and only the ambient term of the SH coefficients are needed
FOneBandSHVectorRGB TranslucentLighting;
TranslucentLighting.R.V.x = AmbientLightingVector.r;
TranslucentLighting.G.V.x = AmbientLightingVector.g;
TranslucentLighting.B.V.x = AmbientLightingVector.b;
FOneBandSHVector DiffuseTransferSH = CalcDiffuseTransferSH1(1);
VolumeLighting = float4(DotSH1(TranslucentLighting, DiffuseTransferSH), AmbientLightingVector.a);
InterpolatedLighting = DiffuseColor * VolumeLighting.rgb;
}
void GetVolumeLightingDirectional(float4 AmbientLightingVector, float3 DirectionalLightingVector, float3 WorldNormal, float3 DiffuseColor, float DirectionalLightingIntensity, inout float3 InterpolatedLighting, out float4 VolumeLighting)
{
// Reconstruct the SH coefficients based on what was encoded
FTwoBandSHVectorRGB TranslucentLighting;
TranslucentLighting.R.V.x = AmbientLightingVector.r;
TranslucentLighting.G.V.x = AmbientLightingVector.g;
TranslucentLighting.B.V.x = AmbientLightingVector.b;
float3 NormalizedAmbientColor = AmbientLightingVector.rgb / (Luminance(AmbientLightingVector.rgb) + 0.00001f);
// Scale the monocrome directional coefficients with the normalzed ambient color as an approximation to the uncompressed values
TranslucentLighting.R.V.yzw = DirectionalLightingVector.rgb * NormalizedAmbientColor.r;
TranslucentLighting.G.V.yzw = DirectionalLightingVector.rgb * NormalizedAmbientColor.g;
TranslucentLighting.B.V.yzw = DirectionalLightingVector.rgb * NormalizedAmbientColor.b;
// Compute diffuse lighting which takes the normal into account
FTwoBandSHVector DiffuseTransferSH = CalcDiffuseTransferSH(WorldNormal * DirectionalLightingIntensity, 1);
VolumeLighting = float4(max(half3(0, 0, 0), DotSH(TranslucentLighting, DiffuseTransferSH)), AmbientLightingVector.a);
InterpolatedLighting += DiffuseColor * VolumeLighting.rgb;
}
float4 GetVolumeLightingDirectional(float4 AmbientLightingVector, float3 DirectionalLightingVector, float3 WorldNormal, float DirectionalLightingIntensity)
{
float3 DiffuseColor = 1.0f;
float3 InterpolatedLighting = 0.0f;
float4 VolumeLighting = 0.0f;
GetVolumeLightingDirectional(AmbientLightingVector, DirectionalLightingVector, WorldNormal, DiffuseColor, DirectionalLightingIntensity, InterpolatedLighting, VolumeLighting);
return VolumeLighting;
}