Files
UnrealEngineUWP/Engine/Shaders/Private/VirtualShadowMaps/VirtualShadowMapTransmissionCommon.ush
Sebastien Hillaire 8e389aec73 Strata - SSS data rework and optimisation for classification and SSS. Gain quite a bit of performance back on low end deferred platforms.
Now header is only uint and extra data is only read if needed.

#rb none
#preflight https://horde.devtools.epicgames.com/job/62821984046b81bf9393b136
#fyi charles.derousiers

[CL 20221584 by Sebastien Hillaire in ue5-main branch]
2022-05-16 05:54:34 -04:00

72 lines
2.7 KiB
Plaintext

// Copyright Epic Games, Inc. All Rights Reserved.
/*=============================================================================
VirtualShadowMaps/VirtualShadowMapTransmissionCommon.ush:
=============================================================================*/
#pragma once
#include "../Common.ush"
#include "../SceneTexturesCommon.ush"
#include "../DeferredShadingCommon.ush"
#include "VirtualShadowMapProjectionCommon.ush"
half GetSubsurfaceOpacityFromGbuffer(uint2 PixelPos)
{
half Opacity = 1.0;
#if STRATA_ENABLED
Opacity = StrataGetOpacityFromSubSurface(StrataLoadSubsurfaceHeader(Strata.SSSTexture, PixelPos));
#else // STRATA_ENABLED
FGBufferData GBufferData = GetGBufferDataUint(PixelPos);
// TODO: SUBSURFACE_PROFILE with fancy transmission
if (GBufferData.ShadingModelID == SHADINGMODELID_SUBSURFACE ||
GBufferData.ShadingModelID == SHADINGMODELID_PREINTEGRATED_SKIN ||
GBufferData.ShadingModelID == SHADINGMODELID_TWOSIDED_FOLIAGE)
{
// This clamp aligns with SubsurfaceDensityFromOpacity
// Various engine paths treat these subsurface materials differently
// even when they have Opacity = 1 in the material shader, so this is
// important to avoid things like backface transmission being shadowed by
// contact shadows and so on.
Opacity = min(GBufferData.CustomData.a, 0.99f);
}
#endif // STRATA_ENABLED
return Opacity;
}
/**
* Sample VSM to determine approximate thickness and compute simple subsurface transmission matching the
* PCF path.
*/
half ComputeSimpleSubsurfaceTransmissionFromVirtualShadowMap(
int VirtualShadowMapId,
float3 TranslatedWorldPosition,
half SubsurfaceOpacity)
{
// If the receiver is a subsurface material, we do a very simple transmission approximation
// This matches the logic in the PCF kernel (ShadowFilteringCommon.ush) and the contact
// shadows trace (DeferredLightingCommon.ush). Ideally these should all be unified in a single location.
// Could optimize this in the case where we are doing single-sample VSM lookup anyways, but we would need
// exclude contact shadows overwriting the occluder distance. Single sample direct shadows are not currently
// a common case.
// Do a separate unfiltered lookup to get approximate occluder distance
FVirtualShadowMapSampleResult SSSResult = SampleVirtualShadowMapTranslatedWorld(
VirtualShadowMapId,
TranslatedWorldPosition,
0.0f // RayStartDistance
);
if ( SSSResult.bValid && SSSResult.ShadowFactor < 1.0f )
{
float Density = SubsurfaceDensityFromOpacity( SubsurfaceOpacity );
float Occlusion = 1.0f - saturate( exp( -Density * SSSResult.OccluderDistance ) );
// NOTE: This square is arbitrary, but we have to be consistent with the PCF path
return Square( 1.0f - Occlusion * ( 1.0f - SSSResult.ShadowFactor ) );
}
return 1.0f;
}