2019-12-26 14:45:42 -05:00
// Copyright Epic Games, Inc. All Rights Reserved.
2018-12-11 22:25:04 -05:00
/*=============================================================================
MobileBasePassRendering . cpp : Base pass rendering implementation .
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
# include "MobileBasePassRendering.h"
# include "TranslucentRendering.h"
# include "DynamicPrimitiveDrawing.h"
# include "ScenePrivate.h"
# include "ShaderPlatformQualitySettings.h"
# include "MaterialShaderQualitySettings.h"
# include "PrimitiveSceneInfo.h"
# include "MeshPassProcessor.inl"
2021-03-08 07:16:20 -04:00
# include "Engine/TextureCube.h"
2018-12-11 22:25:04 -05:00
2022-04-22 01:15:27 -04:00
uint8 GetMobileShadingModelStencilValue ( FMaterialShadingModelField ShadingModel )
{
if ( ShadingModel . HasOnlyShadingModel ( MSM_DefaultLit ) )
{
return 1u ;
}
else if ( ShadingModel . HasOnlyShadingModel ( MSM_Unlit ) )
{
return 0u ;
}
2022-05-11 03:17:42 -04:00
// mark everyhing as MSM_DefaultLit if GBuffer CustomData is not supported
return MobileUsesGBufferCustomData ( GMaxRHIShaderPlatform ) ? 2u : 1u ;
2022-04-22 01:15:27 -04:00
}
2021-11-07 23:43:01 -05:00
bool MobileUsesNoLightMapPermutation ( const FMeshMaterialShaderPermutationParameters & Parameters )
{
static const auto AllowStaticLightingVar = IConsoleManager : : Get ( ) . FindTConsoleVariableDataInt ( TEXT ( " r.AllowStaticLighting " ) ) ;
const bool bAllowStaticLighting = ( ! AllowStaticLightingVar | | AllowStaticLightingVar - > GetValueOnAnyThread ( ) ! = 0 ) ;
const bool bIsLitMaterial = Parameters . MaterialParameters . ShadingModels . IsLit ( ) ;
const bool bDeferredShading = IsMobileDeferredShadingEnabled ( Parameters . Platform ) ;
if ( ! bDeferredShading & & ! bAllowStaticLighting & & bIsLitMaterial & & ! IsTranslucentBlendMode ( Parameters . MaterialParameters . BlendMode ) )
{
// We don't need NoLightMap permutation if CSM shader can handle no-CSM case with a branch inside shader
return ! MobileUseCSMShaderBranch ( ) ;
}
return true ;
}
2022-04-18 09:09:40 -04:00
template < ELightMapPolicyType Policy , bool bEnableLocalLights >
2020-10-22 19:19:16 -04:00
bool GetUniformMobileBasePassShaders (
2018-12-11 22:25:04 -05:00
const FMaterial & Material ,
FVertexFactoryType * VertexFactoryType ,
bool bEnableSkyLight ,
2020-02-06 13:13:41 -05:00
TShaderRef < TMobileBasePassVSPolicyParamType < FUniformLightMapPolicy > > & VertexShader ,
TShaderRef < TMobileBasePassPSPolicyParamType < FUniformLightMapPolicy > > & PixelShader
2018-12-11 22:25:04 -05:00
)
{
2020-02-06 13:13:41 -05:00
using FVertexShaderType = TMobileBasePassVSPolicyParamType < FUniformLightMapPolicy > ;
using FPixelShaderType = TMobileBasePassPSPolicyParamType < FUniformLightMapPolicy > ;
2020-10-22 19:19:16 -04:00
FMaterialShaderTypes ShaderTypes ;
2018-12-11 22:25:04 -05:00
if ( IsMobileHDR ( ) )
{
2020-10-22 19:19:16 -04:00
ShaderTypes . AddShaderType < TMobileBasePassVS < TUniformLightMapPolicy < Policy > , HDR_LINEAR_64 > > ( ) ;
2018-12-11 22:25:04 -05:00
if ( bEnableSkyLight )
{
2022-04-18 09:09:40 -04:00
ShaderTypes . AddShaderType < TMobileBasePassPS < TUniformLightMapPolicy < Policy > , HDR_LINEAR_64 , true , bEnableLocalLights > > ( ) ;
2018-12-11 22:25:04 -05:00
}
else
{
2022-04-18 09:09:40 -04:00
ShaderTypes . AddShaderType < TMobileBasePassPS < TUniformLightMapPolicy < Policy > , HDR_LINEAR_64 , false , bEnableLocalLights > > ( ) ;
2018-12-11 22:25:04 -05:00
}
}
else
{
2020-10-22 19:19:16 -04:00
ShaderTypes . AddShaderType < TMobileBasePassVS < TUniformLightMapPolicy < Policy > , LDR_GAMMA_32 > > ( ) ;
2018-12-11 22:25:04 -05:00
if ( bEnableSkyLight )
{
2022-04-18 09:09:40 -04:00
ShaderTypes . AddShaderType < TMobileBasePassPS < TUniformLightMapPolicy < Policy > , LDR_GAMMA_32 , true , bEnableLocalLights > > ( ) ;
2018-12-11 22:25:04 -05:00
}
else
{
2022-04-18 09:09:40 -04:00
ShaderTypes . AddShaderType < TMobileBasePassPS < TUniformLightMapPolicy < Policy > , LDR_GAMMA_32 , false , bEnableLocalLights > > ( ) ;
2018-12-11 22:25:04 -05:00
}
}
2020-10-22 19:19:16 -04:00
FMaterialShaders Shaders ;
if ( ! Material . TryGetShaders ( ShaderTypes , VertexFactoryType , Shaders ) )
{
return false ;
}
Shaders . TryGetVertexShader ( VertexShader ) ;
Shaders . TryGetPixelShader ( PixelShader ) ;
return true ;
2018-12-11 22:25:04 -05:00
}
2022-04-18 09:09:40 -04:00
template < bool bEnableLocalLights >
2020-10-22 19:19:16 -04:00
bool GetMobileBasePassShaders (
2018-12-11 22:25:04 -05:00
ELightMapPolicyType LightMapPolicyType ,
const FMaterial & Material ,
FVertexFactoryType * VertexFactoryType ,
bool bEnableSkyLight ,
2020-02-06 13:13:41 -05:00
TShaderRef < TMobileBasePassVSPolicyParamType < FUniformLightMapPolicy > > & VertexShader ,
TShaderRef < TMobileBasePassPSPolicyParamType < FUniformLightMapPolicy > > & PixelShader
2018-12-11 22:25:04 -05:00
)
{
switch ( LightMapPolicyType )
{
2021-04-08 14:32:07 -04:00
case LMP_NO_LIGHTMAP :
2022-04-18 09:09:40 -04:00
return GetUniformMobileBasePassShaders < LMP_NO_LIGHTMAP , bEnableLocalLights > ( Material , VertexFactoryType , bEnableSkyLight , VertexShader , PixelShader ) ;
2018-12-11 22:25:04 -05:00
case LMP_LQ_LIGHTMAP :
2022-04-18 09:09:40 -04:00
return GetUniformMobileBasePassShaders < LMP_LQ_LIGHTMAP , bEnableLocalLights > ( Material , VertexFactoryType , bEnableSkyLight , VertexShader , PixelShader ) ;
2018-12-11 22:25:04 -05:00
case LMP_MOBILE_DISTANCE_FIELD_SHADOWS_AND_LQ_LIGHTMAP :
2022-04-18 09:09:40 -04:00
return GetUniformMobileBasePassShaders < LMP_MOBILE_DISTANCE_FIELD_SHADOWS_AND_LQ_LIGHTMAP , bEnableLocalLights > ( Material , VertexFactoryType , bEnableSkyLight , VertexShader , PixelShader ) ;
2021-04-08 14:32:07 -04:00
case LMP_MOBILE_DISTANCE_FIELD_SHADOWS_LIGHTMAP_AND_CSM :
2022-04-18 09:09:40 -04:00
return GetUniformMobileBasePassShaders < LMP_MOBILE_DISTANCE_FIELD_SHADOWS_LIGHTMAP_AND_CSM , bEnableLocalLights > ( Material , VertexFactoryType , bEnableSkyLight , VertexShader , PixelShader ) ;
2021-04-08 14:32:07 -04:00
case LMP_MOBILE_DIRECTIONAL_LIGHT_CSM_AND_LIGHTMAP :
2022-04-18 09:09:40 -04:00
return GetUniformMobileBasePassShaders < LMP_MOBILE_DIRECTIONAL_LIGHT_CSM_AND_LIGHTMAP , bEnableLocalLights > ( Material , VertexFactoryType , bEnableSkyLight , VertexShader , PixelShader ) ;
2018-12-11 22:25:04 -05:00
case LMP_MOBILE_DIRECTIONAL_LIGHT_AND_SH_INDIRECT :
2022-04-18 09:09:40 -04:00
return GetUniformMobileBasePassShaders < LMP_MOBILE_DIRECTIONAL_LIGHT_AND_SH_INDIRECT , bEnableLocalLights > ( Material , VertexFactoryType , bEnableSkyLight , VertexShader , PixelShader ) ;
2021-04-08 14:32:07 -04:00
case LMP_MOBILE_DIRECTIONAL_LIGHT_CSM_AND_SH_INDIRECT :
2022-04-18 09:09:40 -04:00
return GetUniformMobileBasePassShaders < LMP_MOBILE_DIRECTIONAL_LIGHT_CSM_AND_SH_INDIRECT , bEnableLocalLights > ( Material , VertexFactoryType , bEnableSkyLight , VertexShader , PixelShader ) ;
2018-12-11 22:25:04 -05:00
case LMP_MOBILE_MOVABLE_DIRECTIONAL_LIGHT_WITH_LIGHTMAP :
2022-04-18 09:09:40 -04:00
return GetUniformMobileBasePassShaders < LMP_MOBILE_MOVABLE_DIRECTIONAL_LIGHT_WITH_LIGHTMAP , bEnableLocalLights > ( Material , VertexFactoryType , bEnableSkyLight , VertexShader , PixelShader ) ;
2021-04-08 14:32:07 -04:00
case LMP_MOBILE_MOVABLE_DIRECTIONAL_LIGHT_CSM_WITH_LIGHTMAP :
2022-04-18 09:09:40 -04:00
return GetUniformMobileBasePassShaders < LMP_MOBILE_MOVABLE_DIRECTIONAL_LIGHT_CSM_WITH_LIGHTMAP , bEnableLocalLights > ( Material , VertexFactoryType , bEnableSkyLight , VertexShader , PixelShader ) ;
2021-04-08 14:32:07 -04:00
case LMP_MOBILE_DIRECTIONAL_LIGHT_CSM :
2022-04-18 09:09:40 -04:00
return GetUniformMobileBasePassShaders < LMP_MOBILE_DIRECTIONAL_LIGHT_CSM , bEnableLocalLights > ( Material , VertexFactoryType , bEnableSkyLight , VertexShader , PixelShader ) ;
2018-12-11 22:25:04 -05:00
default :
check ( false ) ;
2020-10-22 19:19:16 -04:00
return true ;
2018-12-11 22:25:04 -05:00
}
}
2020-10-22 19:19:16 -04:00
bool MobileBasePass : : GetShaders (
2018-12-11 22:25:04 -05:00
ELightMapPolicyType LightMapPolicyType ,
2022-04-18 09:09:40 -04:00
bool bEnableLocalLights ,
2018-12-11 22:25:04 -05:00
const FMaterial & MaterialResource ,
FVertexFactoryType * VertexFactoryType ,
bool bEnableSkyLight ,
2020-02-06 13:13:41 -05:00
TShaderRef < TMobileBasePassVSPolicyParamType < FUniformLightMapPolicy > > & VertexShader ,
TShaderRef < TMobileBasePassPSPolicyParamType < FUniformLightMapPolicy > > & PixelShader )
2018-12-11 22:25:04 -05:00
{
2019-05-06 06:04:18 -04:00
bool bIsLit = ( MaterialResource . GetShadingModels ( ) . IsLit ( ) ) ;
2018-12-11 22:25:04 -05:00
if ( bIsLit & & ! UseSkylightPermutation ( bEnableSkyLight , FReadOnlyCVARCache : : Get ( ) . MobileSkyLightPermutation ) )
{
bEnableSkyLight = ! bEnableSkyLight ;
}
2020-10-22 19:19:16 -04:00
2022-04-18 09:09:40 -04:00
if ( bEnableLocalLights )
2018-12-11 22:25:04 -05:00
{
2022-04-18 09:09:40 -04:00
return GetMobileBasePassShaders < true > (
2018-12-11 22:25:04 -05:00
LightMapPolicyType ,
MaterialResource ,
VertexFactoryType ,
bEnableSkyLight ,
VertexShader ,
PixelShader
) ;
2022-04-18 09:09:40 -04:00
}
else
{
return GetMobileBasePassShaders < false > (
2018-12-11 22:25:04 -05:00
LightMapPolicyType ,
MaterialResource ,
VertexFactoryType ,
bEnableSkyLight ,
VertexShader ,
PixelShader
) ;
}
}
2019-01-14 22:43:34 -05:00
static bool UseSkyReflectionCapture ( const FScene * RenderScene )
2018-12-11 22:25:04 -05:00
{
return RenderScene
& & RenderScene - > SkyLight
2020-09-24 00:43:27 -04:00
& & RenderScene - > SkyLight - > ProcessedTexture
2018-12-11 22:25:04 -05:00
& & RenderScene - > SkyLight - > ProcessedTexture - > TextureRHI ;
}
const FLightSceneInfo * MobileBasePass : : GetDirectionalLightInfo ( const FScene * Scene , const FPrimitiveSceneProxy * PrimitiveSceneProxy )
{
const FLightSceneInfo * MobileDirectionalLight = nullptr ;
if ( PrimitiveSceneProxy & & Scene )
{
const int32 LightChannel = GetFirstLightingChannelFromMask ( PrimitiveSceneProxy - > GetLightingChannelMask ( ) ) ;
MobileDirectionalLight = LightChannel > = 0 ? Scene - > MobileDirectionalLights [ LightChannel ] : nullptr ;
}
return MobileDirectionalLight ;
}
bool MobileBasePass : : StaticCanReceiveCSM ( const FLightSceneInfo * LightSceneInfo , const FPrimitiveSceneProxy * PrimitiveSceneProxy )
{
// For movable directional lights, when CSM culling is disabled the default behavior is to receive CSM.
static auto * CVarMobileEnableMovableLightCSMShaderCulling = IConsoleManager : : Get ( ) . FindTConsoleVariableDataInt ( TEXT ( " r.Mobile.EnableMovableLightCSMShaderCulling " ) ) ;
if ( LightSceneInfo & & LightSceneInfo - > Proxy - > IsMovable ( ) & & CVarMobileEnableMovableLightCSMShaderCulling - > GetValueOnRenderThread ( ) = = 0 )
{
return true ;
}
// If culling is enabled then CSM receiving is determined during InitDynamicShadows.
// If culling is disabled then stationary directional lights default to no CSM.
return false ;
}
ELightMapPolicyType MobileBasePass : : SelectMeshLightmapPolicy (
const FScene * Scene ,
const FMeshBatch & Mesh ,
const FPrimitiveSceneProxy * PrimitiveSceneProxy ,
const FLightSceneInfo * MobileDirectionalLight ,
2019-05-06 06:04:18 -04:00
FMaterialShadingModelField ShadingModels ,
2020-09-24 00:43:27 -04:00
bool bPrimReceivesCSM ,
2021-04-08 14:32:07 -04:00
bool bUsesDeferredShading ,
2020-09-24 00:43:27 -04:00
ERHIFeatureLevel : : Type FeatureLevel ,
EBlendMode BlendMode )
2018-12-11 22:25:04 -05:00
{
// Unlit uses NoLightmapPolicy with 0 point lights
ELightMapPolicyType SelectedLightmapPolicy = LMP_NO_LIGHTMAP ;
2020-09-24 00:43:27 -04:00
2019-05-06 06:04:18 -04:00
const bool bIsLitMaterial = ShadingModels . IsLit ( ) ;
2018-12-11 22:25:04 -05:00
if ( bIsLitMaterial )
{
const FReadOnlyCVARCache & ReadOnlyCVARCache = FReadOnlyCVARCache : : Get ( ) ;
2022-02-25 00:10:44 -05:00
if ( ! ReadOnlyCVARCache . bAllowStaticLighting | | ( ReadOnlyCVARCache . bMobileEnableNoPrecomputedLightingCSMShader & & Scene & & Scene - > GetForceNoPrecomputedLighting ( ) ) )
2018-12-11 22:25:04 -05:00
{
2021-04-08 14:32:07 -04:00
if ( ! IsTranslucentBlendMode ( BlendMode ) )
2018-12-11 22:25:04 -05:00
{
2021-04-08 14:32:07 -04:00
// Whether to use a single CSM permutation with a branch in the shader
bPrimReceivesCSM | = MobileUseCSMShaderBranch ( ) ;
}
// no precomputed lighting
if ( ! bPrimReceivesCSM | | bUsesDeferredShading )
{
SelectedLightmapPolicy = LMP_NO_LIGHTMAP ;
2018-12-11 22:25:04 -05:00
}
else
{
2021-04-08 14:32:07 -04:00
SelectedLightmapPolicy = LMP_MOBILE_DIRECTIONAL_LIGHT_CSM ;
2018-12-11 22:25:04 -05:00
}
}
2021-04-08 14:32:07 -04:00
else
2018-12-11 22:25:04 -05:00
{
2021-04-08 14:32:07 -04:00
// Check for a cached light-map.
const FLightMapInteraction LightMapInteraction = ( Mesh . LCI ! = nullptr )
? Mesh . LCI - > GetLightMapInteraction ( FeatureLevel )
: FLightMapInteraction ( ) ;
const bool bUseMovableLight = MobileDirectionalLight & & ! MobileDirectionalLight - > Proxy - > HasStaticShadowing ( ) & & ReadOnlyCVARCache . bMobileAllowMovableDirectionalLights ;
const bool bUseStaticAndCSM = MobileDirectionalLight & & MobileDirectionalLight - > Proxy - > UseCSMForDynamicObjects ( )
& & bPrimReceivesCSM
& & ReadOnlyCVARCache . bMobileEnableStaticAndCSMShadowReceivers ;
const bool bMovableWithCSM = bUseMovableLight & & MobileDirectionalLight - > ShouldRenderViewIndependentWholeSceneShadows ( ) & & bPrimReceivesCSM ;
const bool bPrimitiveUsesILC = PrimitiveSceneProxy
& & ( PrimitiveSceneProxy - > IsMovable ( ) | | PrimitiveSceneProxy - > NeedsUnbuiltPreviewLighting ( ) | | PrimitiveSceneProxy - > GetLightmapType ( ) = = ELightmapType : : ForceVolumetric )
& & PrimitiveSceneProxy - > WillEverBeLit ( )
& & PrimitiveSceneProxy - > GetIndirectLightingCacheQuality ( ) ! = ILCQ_Off ;
const bool bHasValidVLM = Scene & & Scene - > VolumetricLightmapSceneData . HasData ( ) ;
const bool bHasValidILC = Scene & & Scene - > PrecomputedLightVolumes . Num ( ) > 0
& & IsIndirectLightingCacheAllowed ( FeatureLevel ) ;
if ( LightMapInteraction . GetType ( ) = = LMIT_Texture & & ReadOnlyCVARCache . bEnableLowQualityLightmaps )
2018-12-11 22:25:04 -05:00
{
2021-04-08 14:32:07 -04:00
// Lightmap path
2020-09-24 00:43:27 -04:00
if ( bUseMovableLight )
{
2021-04-08 14:32:07 -04:00
if ( bUsesDeferredShading )
{
SelectedLightmapPolicy = LMP_LQ_LIGHTMAP ;
}
else if ( bMovableWithCSM & & ! bUsesDeferredShading )
{
SelectedLightmapPolicy = LMP_MOBILE_MOVABLE_DIRECTIONAL_LIGHT_CSM_WITH_LIGHTMAP ;
}
else
{
SelectedLightmapPolicy = LMP_MOBILE_MOVABLE_DIRECTIONAL_LIGHT_WITH_LIGHTMAP ;
}
}
else
{
const FShadowMapInteraction ShadowMapInteraction = ( Mesh . LCI ! = nullptr )
? Mesh . LCI - > GetShadowMapInteraction ( FeatureLevel )
: FShadowMapInteraction ( ) ;
if ( bUseStaticAndCSM & & ! bUsesDeferredShading )
{
if ( ShadowMapInteraction . GetType ( ) = = SMIT_Texture & &
MobileDirectionalLight - > ShouldRenderViewIndependentWholeSceneShadows ( ) & &
ReadOnlyCVARCache . bMobileAllowDistanceFieldShadows )
{
SelectedLightmapPolicy = LMP_MOBILE_DISTANCE_FIELD_SHADOWS_LIGHTMAP_AND_CSM ;
}
else
{
SelectedLightmapPolicy = LMP_MOBILE_DIRECTIONAL_LIGHT_CSM_AND_LIGHTMAP ;
}
}
else
{
if ( ShadowMapInteraction . GetType ( ) = = SMIT_Texture & &
ReadOnlyCVARCache . bMobileAllowDistanceFieldShadows )
{
SelectedLightmapPolicy = LMP_MOBILE_DISTANCE_FIELD_SHADOWS_AND_LQ_LIGHTMAP ;
}
else
{
SelectedLightmapPolicy = LMP_LQ_LIGHTMAP ;
}
}
}
}
else if ( ( bHasValidVLM | | bHasValidILC ) & & bPrimitiveUsesILC )
{
2022-03-02 15:20:01 -05:00
if ( ( bUseStaticAndCSM | | bMovableWithCSM ) & & ! bUsesDeferredShading & & ReadOnlyCVARCache . bMobileEnableStaticAndCSMShadowReceivers )
2021-04-08 14:32:07 -04:00
{
SelectedLightmapPolicy = LMP_MOBILE_DIRECTIONAL_LIGHT_CSM_AND_SH_INDIRECT ;
2020-09-24 00:43:27 -04:00
}
else
{
SelectedLightmapPolicy = LMP_MOBILE_DIRECTIONAL_LIGHT_AND_SH_INDIRECT ;
}
2018-12-11 22:25:04 -05:00
}
}
}
return SelectedLightmapPolicy ;
}
2021-08-12 09:49:16 -04:00
void MobileBasePass : : SetOpaqueRenderState ( FMeshPassProcessorRenderState & DrawRenderState , const FPrimitiveSceneProxy * PrimitiveSceneProxy , const FMaterial & Material , bool bEnableReceiveDecalOutput , bool bUsesDeferredShading )
2018-12-11 22:25:04 -05:00
{
2020-09-24 00:43:27 -04:00
uint8 StencilValue = 0 ;
2018-12-11 22:25:04 -05:00
if ( bEnableReceiveDecalOutput )
{
2020-09-24 00:43:27 -04:00
uint8 ReceiveDecals = ( PrimitiveSceneProxy & & ! PrimitiveSceneProxy - > ReceivesDecals ( ) ? 0x01 : 0x00 ) ;
2022-04-13 01:56:42 -04:00
StencilValue | = GET_STENCIL_BIT_MASK ( RECEIVE_DECAL , ReceiveDecals ) ;
2020-09-24 00:43:27 -04:00
}
if ( bUsesDeferredShading )
{
2022-04-22 01:15:27 -04:00
uint8 ShadingModel = GetMobileShadingModelStencilValue ( Material . GetShadingModels ( ) ) ;
2022-04-13 01:56:42 -04:00
StencilValue | = GET_STENCIL_MOBILE_SM_MASK ( ShadingModel ) ;
StencilValue | = STENCIL_LIGHTING_CHANNELS_MASK ( PrimitiveSceneProxy ? PrimitiveSceneProxy - > GetLightingChannelStencilValue ( ) : 0x00 ) ;
2020-09-24 00:43:27 -04:00
}
2018-12-11 22:25:04 -05:00
2020-09-24 00:43:27 -04:00
if ( bEnableReceiveDecalOutput | | bUsesDeferredShading )
{
2021-08-12 09:49:16 -04:00
DrawRenderState . SetDepthStencilState ( TStaticDepthStencilState <
2018-12-11 22:25:04 -05:00
true , CF_DepthNearOrEqual ,
true , CF_Always , SO_Keep , SO_Keep , SO_Replace ,
false , CF_Always , SO_Keep , SO_Keep , SO_Keep ,
2019-03-12 07:09:02 -04:00
// don't use masking as it has significant performance hit on Mali GPUs (T860MP2)
2020-09-24 00:43:27 -04:00
0x00 , 0xff > : : GetRHI ( ) ) ;
2019-06-17 11:58:25 -04:00
2020-09-24 00:43:27 -04:00
DrawRenderState . SetStencilRef ( StencilValue ) ;
2018-12-11 22:25:04 -05:00
}
else
{
// default depth state should be already set
}
2020-09-24 00:43:27 -04:00
if ( Material . GetBlendMode ( ) = = BLEND_Masked & & Material . IsUsingAlphaToCoverage ( ) )
{
DrawRenderState . SetBlendState ( TStaticBlendState < CW_RGB , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_RGBA , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_RGBA , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_RGBA , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_RGBA , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_RGBA , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_RGBA , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_RGBA , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
true > : : GetRHI ( ) ) ;
}
2018-12-11 22:25:04 -05:00
}
2019-01-16 16:09:39 -05:00
void MobileBasePass : : SetTranslucentRenderState ( FMeshPassProcessorRenderState & DrawRenderState , const FMaterial & Material )
2018-12-11 22:25:04 -05:00
{
2020-09-24 00:43:27 -04:00
const bool bIsUsingMobilePixelProjectedReflection = Material . IsUsingPlanarForwardReflections ( ) & & IsUsingMobilePixelProjectedReflection ( GetFeatureLevelShaderPlatform ( Material . GetFeatureLevel ( ) ) ) ;
2020-02-12 13:27:19 -05:00
if ( Material . GetShadingModels ( ) . HasShadingModel ( MSM_ThinTranslucent ) )
{
// the mobile thin translucent fallback uses a similar mode as BLEND_Translucent, but multiplies color by 1 insead of SrcAlpha.
2022-04-22 08:07:57 -04:00
DrawRenderState . SetBlendState ( TStaticBlendState < CW_RGBA , BO_Add , BF_One , BF_InverseSourceAlpha , BO_Add , BF_Zero , BF_InverseSourceAlpha ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero > : : GetRHI ( ) ) ;
2020-02-12 13:27:19 -05:00
}
else
2018-12-11 22:25:04 -05:00
{
switch ( Material . GetBlendMode ( ) )
{
case BLEND_Translucent :
if ( Material . ShouldWriteOnlyAlpha ( ) )
{
2022-04-22 08:07:57 -04:00
DrawRenderState . SetBlendState ( TStaticBlendState < CW_ALPHA , BO_Add , BF_Zero , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero > : : GetRHI ( ) ) ;
2020-02-12 13:27:19 -05:00
}
2018-12-11 22:25:04 -05:00
else
{
2022-04-22 08:07:57 -04:00
DrawRenderState . SetBlendState ( TStaticBlendState < CW_RGBA , BO_Add , BF_SourceAlpha , BF_InverseSourceAlpha , BO_Add , BF_Zero , BF_InverseSourceAlpha ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero > : : GetRHI ( ) ) ;
2018-12-11 22:25:04 -05:00
}
break ;
case BLEND_Additive :
// Add to the existing scene color
2022-04-22 08:07:57 -04:00
DrawRenderState . SetBlendState ( TStaticBlendState < CW_RGBA , BO_Add , BF_One , BF_One , BO_Add , BF_Zero , BF_InverseSourceAlpha ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero > : : GetRHI ( ) ) ;
2018-12-11 22:25:04 -05:00
break ;
case BLEND_Modulate :
2021-09-29 02:54:29 -04:00
// Modulate with the existing scene color, preserve destination alpha.
2022-04-22 08:07:57 -04:00
DrawRenderState . SetBlendState ( TStaticBlendState < CW_RGB , BO_Add , BF_DestColor , BF_Zero , BO_Add , BF_Zero , BF_One ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero > : : GetRHI ( ) ) ;
2018-12-11 22:25:04 -05:00
break ;
case BLEND_AlphaComposite :
// Blend with existing scene color. New color is already pre-multiplied by alpha.
2022-04-22 08:07:57 -04:00
DrawRenderState . SetBlendState ( TStaticBlendState < CW_RGBA , BO_Add , BF_One , BF_InverseSourceAlpha , BO_Add , BF_Zero , BF_InverseSourceAlpha ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero > : : GetRHI ( ) ) ;
2018-12-11 22:25:04 -05:00
break ;
2019-06-11 18:27:07 -04:00
case BLEND_AlphaHoldout :
// Blend by holding out the matte shape of the source alpha
2022-04-22 08:07:57 -04:00
DrawRenderState . SetBlendState ( TStaticBlendState < CW_RGBA , BO_Add , BF_Zero , BF_InverseSourceAlpha , BO_Add , BF_One , BF_InverseSourceAlpha ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero > : : GetRHI ( ) ) ;
2018-12-11 22:25:04 -05:00
break ;
default :
2019-09-19 12:41:44 -04:00
if ( Material . GetShadingModels ( ) . HasShadingModel ( MSM_SingleLayerWater ) )
2019-09-18 20:56:27 -04:00
{
// Single layer water is an opaque marerial rendered as translucent on Mobile. We force pre-multiplied alpha to achieve water depth based transmittance.
2022-04-22 08:07:57 -04:00
DrawRenderState . SetBlendState ( TStaticBlendState < CW_RGBA , BO_Add , BF_One , BF_InverseSourceAlpha , BO_Add , BF_Zero , BF_InverseSourceAlpha ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero ,
CW_NONE , BO_Add , BF_One , BF_Zero , BO_Add , BF_One , BF_Zero > : : GetRHI ( ) ) ;
2019-09-18 20:56:27 -04:00
}
else
2020-02-12 13:27:19 -05:00
{
check ( 0 ) ;
}
2018-12-11 22:25:04 -05:00
} ;
}
if ( Material . ShouldDisableDepthTest ( ) )
{
DrawRenderState . SetDepthStencilState ( TStaticDepthStencilState < false , CF_Always > : : GetRHI ( ) ) ;
}
}
2021-02-18 18:13:28 -04:00
bool MobileBasePass : : StationarySkyLightHasBeenApplied ( const FScene * Scene , ELightMapPolicyType LightMapPolicyType )
{
return Scene
& & Scene - > SkyLight
& & Scene - > SkyLight - > bWantsStaticShadowing
& & ( LightMapPolicyType = = LMP_LQ_LIGHTMAP
| | LightMapPolicyType = = LMP_MOBILE_DISTANCE_FIELD_SHADOWS_AND_LQ_LIGHTMAP
2021-04-08 14:32:07 -04:00
| | LightMapPolicyType = = LMP_MOBILE_DISTANCE_FIELD_SHADOWS_LIGHTMAP_AND_CSM
| | LightMapPolicyType = = LMP_MOBILE_DIRECTIONAL_LIGHT_CSM_AND_LIGHTMAP
| | LightMapPolicyType = = LMP_MOBILE_DIRECTIONAL_LIGHT_AND_SH_INDIRECT
| | LightMapPolicyType = = LMP_MOBILE_DIRECTIONAL_LIGHT_CSM_AND_SH_INDIRECT
| | LightMapPolicyType = = LMP_MOBILE_MOVABLE_DIRECTIONAL_LIGHT_WITH_LIGHTMAP
| | LightMapPolicyType = = LMP_MOBILE_MOVABLE_DIRECTIONAL_LIGHT_CSM_WITH_LIGHTMAP ) ;
2021-02-18 18:13:28 -04:00
}
2019-01-28 22:48:15 -05:00
static FMeshDrawCommandSortKey GetBasePassStaticSortKey ( EBlendMode BlendMode , bool bBackground )
2018-12-11 22:25:04 -05:00
{
FMeshDrawCommandSortKey SortKey ;
SortKey . PackedData = ( BlendMode = = EBlendMode : : BLEND_Masked ? 1 : 0 ) ;
2019-01-28 22:48:15 -05:00
SortKey . PackedData | = ( bBackground ? 2 : 0 ) ; // background flag in second bit
2018-12-11 22:25:04 -05:00
return SortKey ;
}
template < >
void TMobileBasePassPSPolicyParamType < FUniformLightMapPolicy > : : GetShaderBindings (
const FScene * Scene ,
ERHIFeatureLevel : : Type FeatureLevel ,
const FPrimitiveSceneProxy * PrimitiveSceneProxy ,
const FMaterialRenderProxy & MaterialRenderProxy ,
const FMaterial & Material ,
2019-01-17 05:02:52 -05:00
const FMeshPassProcessorRenderState & DrawRenderState ,
2018-12-11 22:25:04 -05:00
const TMobileBasePassShaderElementData < FUniformLightMapPolicy > & ShaderElementData ,
FMeshDrawSingleShaderBindings & ShaderBindings ) const
{
2019-01-17 05:02:52 -05:00
FMeshMaterialShader : : GetShaderBindings ( Scene , FeatureLevel , PrimitiveSceneProxy , MaterialRenderProxy , Material , DrawRenderState , ShaderElementData , ShaderBindings ) ;
2018-12-11 22:25:04 -05:00
FUniformLightMapPolicy : : GetPixelShaderBindings (
PrimitiveSceneProxy ,
ShaderElementData . LightMapPolicyElementData ,
this ,
ShaderBindings ) ;
if ( Scene )
{
2022-04-25 03:36:53 -04:00
if ( ReflectionParameter . IsBound ( ) )
2019-04-10 22:12:58 -04:00
{
2019-06-17 13:39:07 -04:00
FRHIUniformBuffer * ReflectionUB = GDefaultMobileReflectionCaptureUniformBuffer . GetUniformBufferRHI ( ) ;
2021-09-27 19:54:25 -04:00
FPrimitiveSceneInfo * PrimitiveSceneInfo = PrimitiveSceneProxy ? PrimitiveSceneProxy - > GetPrimitiveSceneInfo ( ) : nullptr ;
if ( PrimitiveSceneInfo & & PrimitiveSceneInfo - > CachedReflectionCaptureProxy )
{
ReflectionUB = PrimitiveSceneInfo - > CachedReflectionCaptureProxy - > MobileUniformBuffer ;
}
2021-09-06 12:23:53 -04:00
// If no reflection captures are available then attempt to use sky light's texture.
else if ( UseSkyReflectionCapture ( Scene ) )
{
ReflectionUB = Scene - > UniformBuffers . MobileSkyReflectionUniformBuffer ;
2018-12-11 22:25:04 -05:00
}
2019-06-17 13:39:07 -04:00
ShaderBindings . Add ( ReflectionParameter , ReflectionUB ) ;
2018-12-11 22:25:04 -05:00
}
}
else
{
2019-04-10 22:12:58 -04:00
ensure ( ! ReflectionParameter . IsBound ( ) ) ;
2018-12-11 22:25:04 -05:00
}
// Set directional light UB
2018-12-29 20:07:31 -05:00
if ( MobileDirectionLightBufferParam . IsBound ( ) & & Scene )
2018-12-11 22:25:04 -05:00
{
int32 UniformBufferIndex = PrimitiveSceneProxy ? GetFirstLightingChannelFromMask ( PrimitiveSceneProxy - > GetLightingChannelMask ( ) ) + 1 : 0 ;
ShaderBindings . Add ( MobileDirectionLightBufferParam , Scene - > UniformBuffers . MobileDirectionalLightUniformBuffers [ UniformBufferIndex ] ) ;
}
2020-12-10 14:45:57 -04:00
if ( UseCSMParameter . IsBound ( ) )
{
ShaderBindings . Add ( UseCSMParameter , ShaderElementData . bCanReceiveCSM ? 1 : 0 ) ;
}
2018-12-11 22:25:04 -05:00
}
2019-04-02 18:08:33 -04:00
FMobileBasePassMeshProcessor : : FMobileBasePassMeshProcessor (
const FScene * Scene ,
ERHIFeatureLevel : : Type InFeatureLevel ,
const FSceneView * InViewIfDynamicMeshCommand ,
const FMeshPassProcessorRenderState & InDrawRenderState ,
FMeshPassDrawListContext * InDrawListContext ,
2020-06-23 18:40:00 -04:00
EFlags InFlags ,
2019-04-02 18:08:33 -04:00
ETranslucencyPass : : Type InTranslucencyPassType )
2018-12-11 22:25:04 -05:00
: FMeshPassProcessor ( Scene , InFeatureLevel , InViewIfDynamicMeshCommand , InDrawListContext )
, PassDrawRenderState ( InDrawRenderState )
, TranslucencyPassType ( InTranslucencyPassType )
2020-06-23 18:40:00 -04:00
, Flags ( InFlags )
2018-12-11 22:25:04 -05:00
, bTranslucentBasePass ( InTranslucencyPassType ! = ETranslucencyPass : : TPT_MAX )
2020-09-24 00:43:27 -04:00
, bUsesDeferredShading ( ! bTranslucentBasePass & & IsMobileDeferredShadingEnabled ( GetFeatureLevelShaderPlatform ( InFeatureLevel ) ) )
{
}
2018-12-11 22:25:04 -05:00
2020-10-22 19:19:16 -04:00
bool FMobileBasePassMeshProcessor : : TryAddMeshBatch ( const FMeshBatch & RESTRICT MeshBatch , uint64 BatchElementMask , const FPrimitiveSceneProxy * RESTRICT PrimitiveSceneProxy , int32 StaticMeshId , const FMaterialRenderProxy & MaterialRenderProxy , const FMaterial & Material )
2018-12-11 22:25:04 -05:00
{
const EBlendMode BlendMode = Material . GetBlendMode ( ) ;
2019-05-06 06:04:18 -04:00
const FMaterialShadingModelField ShadingModels = Material . GetShadingModels ( ) ;
2018-12-11 22:25:04 -05:00
const bool bIsTranslucent = IsTranslucentBlendMode ( BlendMode ) ;
2019-09-19 12:41:44 -04:00
const bool bUsesWaterMaterial = ShadingModels . HasShadingModel ( MSM_SingleLayerWater ) ; // Water goes into the translucent pass
2020-06-23 18:40:00 -04:00
const bool bCanReceiveCSM = ( ( Flags & EFlags : : CanReceiveCSM ) = = EFlags : : CanReceiveCSM ) ;
2020-10-22 19:19:16 -04:00
bool bResult = true ;
2018-12-11 22:25:04 -05:00
if ( bTranslucentBasePass )
{
2020-02-12 13:27:19 -05:00
// Skipping TPT_TranslucencyAfterDOFModulate. That pass is only needed for Dual Blending, which is not supported on Mobile.
2021-03-09 00:23:43 -04:00
bool bShouldDraw = ( bIsTranslucent | | bUsesWaterMaterial ) & &
2018-12-11 22:25:04 -05:00
( TranslucencyPassType = = ETranslucencyPass : : TPT_AllTranslucency
| | ( TranslucencyPassType = = ETranslucencyPass : : TPT_StandardTranslucency & & ! Material . IsMobileSeparateTranslucencyEnabled ( ) )
2019-09-26 05:32:11 -04:00
| | ( TranslucencyPassType = = ETranslucencyPass : : TPT_TranslucencyAfterDOF & & Material . IsMobileSeparateTranslucencyEnabled ( ) ) ) ;
2020-02-12 13:27:19 -05:00
2018-12-11 22:25:04 -05:00
if ( bShouldDraw )
{
check ( bCanReceiveCSM = = false ) ;
const FLightSceneInfo * MobileDirectionalLight = MobileBasePass : : GetDirectionalLightInfo ( Scene , PrimitiveSceneProxy ) ;
2020-09-24 00:43:27 -04:00
// Opaque meshes used for mobile pixel projected reflection could receive CSM in translucent pass.
2021-03-09 00:23:43 -04:00
ELightMapPolicyType LightmapPolicyType = MobileBasePass : : SelectMeshLightmapPolicy ( Scene , MeshBatch , PrimitiveSceneProxy , MobileDirectionalLight , ShadingModels , bCanReceiveCSM , false , FeatureLevel , BlendMode ) ;
2020-12-10 14:45:57 -04:00
bResult = Process ( MeshBatch , BatchElementMask , StaticMeshId , PrimitiveSceneProxy , MaterialRenderProxy , Material , BlendMode , ShadingModels , LightmapPolicyType , bCanReceiveCSM , MeshBatch . LCI ) ;
2018-12-11 22:25:04 -05:00
}
}
else
{
// opaque materials.
2021-03-09 00:23:43 -04:00
if ( ! bIsTranslucent & & ! bUsesWaterMaterial )
2018-12-11 22:25:04 -05:00
{
const FLightSceneInfo * MobileDirectionalLight = MobileBasePass : : GetDirectionalLightInfo ( Scene , PrimitiveSceneProxy ) ;
2020-09-24 00:43:27 -04:00
ELightMapPolicyType LightmapPolicyType = MobileBasePass : : SelectMeshLightmapPolicy ( Scene , MeshBatch , PrimitiveSceneProxy , MobileDirectionalLight , ShadingModels , bCanReceiveCSM , bUsesDeferredShading , FeatureLevel , BlendMode ) ;
2020-12-10 14:45:57 -04:00
bResult = Process ( MeshBatch , BatchElementMask , StaticMeshId , PrimitiveSceneProxy , MaterialRenderProxy , Material , BlendMode , ShadingModels , LightmapPolicyType , bCanReceiveCSM , MeshBatch . LCI ) ;
2018-12-11 22:25:04 -05:00
}
}
2020-10-22 19:19:16 -04:00
return bResult ;
}
void FMobileBasePassMeshProcessor : : AddMeshBatch ( const FMeshBatch & RESTRICT MeshBatch , uint64 BatchElementMask , const FPrimitiveSceneProxy * RESTRICT PrimitiveSceneProxy , int32 StaticMeshId )
{
if ( ! MeshBatch . bUseForMaterial | | ( PrimitiveSceneProxy & & ! PrimitiveSceneProxy - > ShouldRenderInMainPass ( ) ) )
{
return ;
}
const FMaterialRenderProxy * MaterialRenderProxy = MeshBatch . MaterialRenderProxy ;
while ( MaterialRenderProxy )
{
const FMaterial * Material = MaterialRenderProxy - > GetMaterialNoFallback ( FeatureLevel ) ;
if ( Material & & Material - > GetRenderingThreadShaderMap ( ) )
{
if ( TryAddMeshBatch ( MeshBatch , BatchElementMask , PrimitiveSceneProxy , StaticMeshId , * MaterialRenderProxy , * Material ) )
{
break ;
}
}
MaterialRenderProxy = MaterialRenderProxy - > GetFallback ( FeatureLevel ) ;
}
2018-12-11 22:25:04 -05:00
}
2020-10-22 19:19:16 -04:00
bool FMobileBasePassMeshProcessor : : Process (
2018-12-11 22:25:04 -05:00
const FMeshBatch & RESTRICT MeshBatch ,
uint64 BatchElementMask ,
2018-12-12 15:27:47 -05:00
int32 StaticMeshId ,
2018-12-11 22:25:04 -05:00
const FPrimitiveSceneProxy * RESTRICT PrimitiveSceneProxy ,
const FMaterialRenderProxy & RESTRICT MaterialRenderProxy ,
const FMaterial & RESTRICT MaterialResource ,
EBlendMode BlendMode ,
2019-05-06 06:04:18 -04:00
FMaterialShadingModelField ShadingModels ,
2018-12-11 22:25:04 -05:00
const ELightMapPolicyType LightMapPolicyType ,
2020-12-10 14:45:57 -04:00
const bool bCanReceiveCSM ,
2018-12-11 22:25:04 -05:00
const FUniformLightMapPolicy : : ElementDataType & RESTRICT LightMapElementData )
{
TMeshProcessorShaders <
TMobileBasePassVSPolicyParamType < FUniformLightMapPolicy > ,
TMobileBasePassPSPolicyParamType < FUniformLightMapPolicy > > BasePassShaders ;
2020-02-13 03:53:21 -05:00
bool bEnableSkyLight = false ;
if ( Scene & & Scene - > SkyLight )
{
2022-04-18 09:09:40 -04:00
// Clustered reflection is always enabled on mobile deferred translucent material
const bool bEnableClusteredReflections = MobileEnableClusteredReflections ( Scene - > GetShaderPlatform ( ) ) ;
2021-02-18 18:13:28 -04:00
//The stationary skylight contribution has been added both to the LowQuality Lightmap and ILC on mobile, so we should skip the sky light spherical harmonic contribution for it.
2022-04-18 09:09:40 -04:00
bool bStationarySkyLightHasBeenApplied = MobileBasePass : : StationarySkyLightHasBeenApplied ( Scene , LightMapPolicyType ) & & ! bEnableClusteredReflections ;
2020-02-13 03:53:21 -05:00
//Two side material should enable sky light for the back face since only the front face has light map and it will be corrected in base pass shader.
2021-02-18 18:13:28 -04:00
bool bSkipStationarySkyLight = bStationarySkyLightHasBeenApplied & & ! MaterialResource . IsTwoSided ( ) ;
2020-02-13 03:53:21 -05:00
2021-02-18 18:13:28 -04:00
bEnableSkyLight = ShadingModels . IsLit ( ) & & Scene - > ShouldRenderSkylightInBasePass ( BlendMode ) & & ( ! bSkipStationarySkyLight ) ;
2020-02-13 03:53:21 -05:00
}
2022-04-18 09:09:40 -04:00
bool bEnableLocalLights = false ;
if ( Scene & & PrimitiveSceneProxy & & ShadingModels . IsLit ( ) )
2020-09-24 00:43:27 -04:00
{
2022-04-18 09:09:40 -04:00
const bool bIsTranslucentMaterialOnDeferred = Scene & & bTranslucentBasePass & & IsMobileDeferredShadingEnabled ( Scene - > GetShaderPlatform ( ) ) ;
// Clustered lighting could only be enabled on mobile forward and always enabled on mobile deferred translucent material
if ( ! bUsesDeferredShading & & ( MobileForwardEnableLocalLights ( Scene - > GetShaderPlatform ( ) ) | | bIsTranslucentMaterialOnDeferred ) )
{
bEnableLocalLights = PrimitiveSceneProxy - > GetPrimitiveSceneInfo ( ) - > NumMobileMovableLocalLights > 0 ;
}
2020-09-24 00:43:27 -04:00
}
2018-12-11 22:25:04 -05:00
2020-10-22 19:19:16 -04:00
if ( ! MobileBasePass : : GetShaders (
LightMapPolicyType ,
2022-04-18 09:09:40 -04:00
bEnableLocalLights ,
2020-10-22 19:19:16 -04:00
MaterialResource ,
MeshBatch . VertexFactory - > GetType ( ) ,
bEnableSkyLight ,
BasePassShaders . VertexShader ,
BasePassShaders . PixelShader ) )
{
return false ;
}
2018-12-11 22:25:04 -05:00
2020-10-22 19:19:16 -04:00
const bool bMaskedInEarlyPass = ( MaterialResource . IsMasked ( ) | | MeshBatch . bDitheredLODTransition ) & & Scene & & MaskedInEarlyPass ( Scene - > GetShaderPlatform ( ) ) ;
2020-06-23 18:40:00 -04:00
const bool bForcePassDrawRenderState = ( ( Flags & EFlags : : ForcePassDrawRenderState ) = = EFlags : : ForcePassDrawRenderState ) ;
2019-01-16 16:09:39 -05:00
FMeshPassProcessorRenderState DrawRenderState ( PassDrawRenderState ) ;
2020-06-23 18:40:00 -04:00
if ( ! bForcePassDrawRenderState )
2018-12-11 22:25:04 -05:00
{
2020-06-23 18:40:00 -04:00
if ( bTranslucentBasePass )
{
MobileBasePass : : SetTranslucentRenderState ( DrawRenderState , MaterialResource ) ;
}
2021-08-12 09:49:16 -04:00
else if ( ( MeshBatch . bUseForDepthPass & & Scene - > EarlyZPassMode = = DDM_AllOpaque ) | | bMaskedInEarlyPass )
{
DrawRenderState . SetDepthStencilState ( TStaticDepthStencilState < false , CF_Equal > : : GetRHI ( ) ) ;
}
2020-06-23 18:40:00 -04:00
else
{
const bool bEnableReceiveDecalOutput = ( ( Flags & EFlags : : CanUseDepthStencil ) = = EFlags : : CanUseDepthStencil ) ;
2021-08-12 09:49:16 -04:00
MobileBasePass : : SetOpaqueRenderState ( DrawRenderState , PrimitiveSceneProxy , MaterialResource , bEnableReceiveDecalOutput & & IsMobileHDR ( ) , bUsesDeferredShading ) ;
2020-06-23 18:40:00 -04:00
}
2018-12-11 22:25:04 -05:00
}
FMeshDrawCommandSortKey SortKey ;
if ( bTranslucentBasePass )
{
2020-09-24 00:43:27 -04:00
const bool bIsUsingMobilePixelProjectedReflection = MaterialResource . IsUsingPlanarForwardReflections ( )
& & IsUsingMobilePixelProjectedReflection ( GetFeatureLevelShaderPlatform ( MaterialResource . GetFeatureLevel ( ) ) ) ;
2019-01-21 09:13:36 -05:00
SortKey = CalculateTranslucentMeshStaticSortKey ( PrimitiveSceneProxy , MeshBatch . MeshIdInPrimitive ) ;
2019-10-01 09:07:48 -04:00
// We always want water to be rendered first on mobile in order to mimic other renderers where it is opaque. We shift the other priorities by 1.
2020-09-24 00:43:27 -04:00
// And we also want to render the meshes used for mobile pixel projected reflection first if it is opaque.
const bool bIsTranslucent = IsTranslucentBlendMode ( BlendMode ) ;
SortKey . Translucent . Priority = ShadingModels . HasShadingModel ( MSM_SingleLayerWater ) | | ( ! bIsTranslucent & & bIsUsingMobilePixelProjectedReflection ) ? uint16 ( 0 ) : uint16 ( FMath : : Clamp ( uint32 ( SortKey . Translucent . Priority ) + 1 , 0u , uint32 ( USHRT_MAX ) ) ) ;
2018-12-11 22:25:04 -05:00
}
else
{
2019-01-28 22:48:15 -05:00
// Background primitives will be rendered last in masked/non-masked buckets
2019-03-15 09:01:09 -04:00
bool bBackground = PrimitiveSceneProxy ? PrimitiveSceneProxy - > TreatAsBackgroundForOcclusion ( ) : false ;
2018-12-11 22:25:04 -05:00
// Default static sort key separates masked and non-masked geometry, generic mesh sorting will also sort by PSO
// if platform wants front to back sorting, this key will be recomputed in InitViews
2019-01-28 22:48:15 -05:00
SortKey = GetBasePassStaticSortKey ( BlendMode , bBackground ) ;
2018-12-11 22:25:04 -05:00
}
2020-02-06 13:13:41 -05:00
const FMeshDrawingPolicyOverrideSettings OverrideSettings = ComputeMeshOverrideSettings ( MeshBatch ) ;
ERasterizerFillMode MeshFillMode = ComputeMeshFillMode ( MeshBatch , MaterialResource , OverrideSettings ) ;
ERasterizerCullMode MeshCullMode = ComputeMeshCullMode ( MeshBatch , MaterialResource , OverrideSettings ) ;
2018-12-11 22:25:04 -05:00
2020-12-10 14:45:57 -04:00
TMobileBasePassShaderElementData < FUniformLightMapPolicy > ShaderElementData ( LightMapElementData , bCanReceiveCSM ) ;
2018-12-12 15:27:47 -05:00
ShaderElementData . InitializeMeshMaterialData ( ViewIfDynamicMeshCommand , PrimitiveSceneProxy , MeshBatch , StaticMeshId , false ) ;
2018-12-11 22:25:04 -05:00
BuildMeshDrawCommands (
MeshBatch ,
BatchElementMask ,
PrimitiveSceneProxy ,
MaterialRenderProxy ,
MaterialResource ,
DrawRenderState ,
BasePassShaders ,
MeshFillMode ,
MeshCullMode ,
SortKey ,
EMeshPassFeatures : : Default ,
ShaderElementData ) ;
2020-10-22 19:19:16 -04:00
return true ;
2018-12-11 22:25:04 -05:00
}
2019-01-12 23:27:39 -05:00
FMeshPassProcessor * CreateMobileBasePassProcessor ( const FScene * Scene , const FSceneView * InViewIfDynamicMeshCommand , FMeshPassDrawListContext * InDrawListContext )
2018-12-11 22:25:04 -05:00
{
2020-12-10 14:45:57 -04:00
FMeshPassProcessorRenderState PassDrawRenderState ;
2018-12-11 22:25:04 -05:00
PassDrawRenderState . SetBlendState ( TStaticBlendStateWriteMask < CW_RGBA > : : GetRHI ( ) ) ;
2019-03-12 10:09:45 -04:00
PassDrawRenderState . SetDepthStencilAccess ( Scene - > DefaultBasePassDepthStencilAccess ) ;
2018-12-11 22:25:04 -05:00
PassDrawRenderState . SetDepthStencilState ( TStaticDepthStencilState < true , CF_DepthNearOrEqual > : : GetRHI ( ) ) ;
2021-09-27 19:54:25 -04:00
const FMobileBasePassMeshProcessor : : EFlags Flags = FMobileBasePassMeshProcessor : : EFlags : : CanUseDepthStencil
| ( MobileBasePassAlwaysUsesCSM ( Scene - > GetShaderPlatform ( ) ) ? FMobileBasePassMeshProcessor : : EFlags : : CanReceiveCSM : FMobileBasePassMeshProcessor : : EFlags : : None ) ;
2019-04-02 18:08:33 -04:00
return new ( FMemStack : : Get ( ) ) FMobileBasePassMeshProcessor ( Scene , Scene - > GetFeatureLevel ( ) , InViewIfDynamicMeshCommand , PassDrawRenderState , InDrawListContext , Flags ) ;
2018-12-11 22:25:04 -05:00
}
2019-01-12 23:27:39 -05:00
FMeshPassProcessor * CreateMobileBasePassCSMProcessor ( const FScene * Scene , const FSceneView * InViewIfDynamicMeshCommand , FMeshPassDrawListContext * InDrawListContext )
2018-12-11 22:25:04 -05:00
{
2020-12-10 14:45:57 -04:00
FMeshPassProcessorRenderState PassDrawRenderState ;
2018-12-11 22:25:04 -05:00
PassDrawRenderState . SetBlendState ( TStaticBlendStateWriteMask < CW_RGBA > : : GetRHI ( ) ) ;
2019-03-12 10:09:45 -04:00
PassDrawRenderState . SetDepthStencilAccess ( Scene - > DefaultBasePassDepthStencilAccess ) ;
2018-12-11 22:25:04 -05:00
PassDrawRenderState . SetDepthStencilState ( TStaticDepthStencilState < true , CF_DepthNearOrEqual > : : GetRHI ( ) ) ;
2019-04-02 18:08:33 -04:00
const FMobileBasePassMeshProcessor : : EFlags Flags = FMobileBasePassMeshProcessor : : EFlags : : CanReceiveCSM | FMobileBasePassMeshProcessor : : EFlags : : CanUseDepthStencil ;
return new ( FMemStack : : Get ( ) ) FMobileBasePassMeshProcessor ( Scene , Scene - > GetFeatureLevel ( ) , InViewIfDynamicMeshCommand , PassDrawRenderState , InDrawListContext , Flags ) ;
2018-12-11 22:25:04 -05:00
}
2019-01-12 23:27:39 -05:00
FMeshPassProcessor * CreateMobileTranslucencyStandardPassProcessor ( const FScene * Scene , const FSceneView * InViewIfDynamicMeshCommand , FMeshPassDrawListContext * InDrawListContext )
2018-12-11 22:25:04 -05:00
{
2020-12-10 14:45:57 -04:00
FMeshPassProcessorRenderState PassDrawRenderState ;
2018-12-11 22:25:04 -05:00
PassDrawRenderState . SetDepthStencilState ( TStaticDepthStencilState < false , CF_DepthNearOrEqual > : : GetRHI ( ) ) ;
PassDrawRenderState . SetDepthStencilAccess ( FExclusiveDepthStencil : : DepthRead_StencilRead ) ;
2019-04-02 18:08:33 -04:00
2019-05-14 17:32:34 -04:00
2019-04-02 18:08:33 -04:00
const FMobileBasePassMeshProcessor : : EFlags Flags = FMobileBasePassMeshProcessor : : EFlags : : CanUseDepthStencil ;
2018-12-11 22:25:04 -05:00
2019-04-02 18:08:33 -04:00
return new ( FMemStack : : Get ( ) ) FMobileBasePassMeshProcessor ( Scene , Scene - > GetFeatureLevel ( ) , InViewIfDynamicMeshCommand , PassDrawRenderState , InDrawListContext , Flags , ETranslucencyPass : : TPT_StandardTranslucency ) ;
2018-12-11 22:25:04 -05:00
}
2019-01-12 23:27:39 -05:00
FMeshPassProcessor * CreateMobileTranslucencyAfterDOFProcessor ( const FScene * Scene , const FSceneView * InViewIfDynamicMeshCommand , FMeshPassDrawListContext * InDrawListContext )
2018-12-11 22:25:04 -05:00
{
2020-12-10 14:45:57 -04:00
FMeshPassProcessorRenderState PassDrawRenderState ;
2018-12-11 22:25:04 -05:00
PassDrawRenderState . SetDepthStencilState ( TStaticDepthStencilState < false , CF_DepthNearOrEqual > : : GetRHI ( ) ) ;
PassDrawRenderState . SetDepthStencilAccess ( FExclusiveDepthStencil : : DepthRead_StencilRead ) ;
2019-04-02 18:08:33 -04:00
const FMobileBasePassMeshProcessor : : EFlags Flags = FMobileBasePassMeshProcessor : : EFlags : : CanUseDepthStencil ;
return new ( FMemStack : : Get ( ) ) FMobileBasePassMeshProcessor ( Scene , Scene - > GetFeatureLevel ( ) , InViewIfDynamicMeshCommand , PassDrawRenderState , InDrawListContext , Flags , ETranslucencyPass : : TPT_TranslucencyAfterDOF ) ;
2018-12-11 22:25:04 -05:00
}
2019-01-12 23:27:39 -05:00
FMeshPassProcessor * CreateMobileTranslucencyAllPassProcessor ( const FScene * Scene , const FSceneView * InViewIfDynamicMeshCommand , FMeshPassDrawListContext * InDrawListContext )
2018-12-11 22:25:04 -05:00
{
2020-12-10 14:45:57 -04:00
FMeshPassProcessorRenderState PassDrawRenderState ;
2018-12-11 22:25:04 -05:00
PassDrawRenderState . SetDepthStencilState ( TStaticDepthStencilState < false , CF_DepthNearOrEqual > : : GetRHI ( ) ) ;
PassDrawRenderState . SetDepthStencilAccess ( FExclusiveDepthStencil : : DepthRead_StencilRead ) ;
2019-04-02 18:08:33 -04:00
const FMobileBasePassMeshProcessor : : EFlags Flags = FMobileBasePassMeshProcessor : : EFlags : : CanUseDepthStencil ;
return new ( FMemStack : : Get ( ) ) FMobileBasePassMeshProcessor ( Scene , Scene - > GetFeatureLevel ( ) , InViewIfDynamicMeshCommand , PassDrawRenderState , InDrawListContext , Flags , ETranslucencyPass : : TPT_AllTranslucency ) ;
2018-12-11 22:25:04 -05:00
}
FRegisterPassProcessorCreateFunction RegisterMobileBasePass ( & CreateMobileBasePassProcessor , EShadingPath : : Mobile , EMeshPass : : BasePass , EMeshPassFlags : : CachedMeshCommands | EMeshPassFlags : : MainView ) ;
FRegisterPassProcessorCreateFunction RegisterMobileBasePassCSM ( & CreateMobileBasePassCSMProcessor , EShadingPath : : Mobile , EMeshPass : : MobileBasePassCSM , EMeshPassFlags : : CachedMeshCommands | EMeshPassFlags : : MainView ) ;
FRegisterPassProcessorCreateFunction RegisterMobileTranslucencyAllPass ( & CreateMobileTranslucencyAllPassProcessor , EShadingPath : : Mobile , EMeshPass : : TranslucencyAll , EMeshPassFlags : : CachedMeshCommands | EMeshPassFlags : : MainView ) ;
FRegisterPassProcessorCreateFunction RegisterMobileTranslucencyStandardPass ( & CreateMobileTranslucencyStandardPassProcessor , EShadingPath : : Mobile , EMeshPass : : TranslucencyStandard , EMeshPassFlags : : CachedMeshCommands | EMeshPassFlags : : MainView ) ;
FRegisterPassProcessorCreateFunction RegisterMobileTranslucencyAfterDOFPass ( & CreateMobileTranslucencyAfterDOFProcessor , EShadingPath : : Mobile , EMeshPass : : TranslucencyAfterDOF , EMeshPassFlags : : CachedMeshCommands | EMeshPassFlags : : MainView ) ;
2020-02-12 13:27:19 -05:00
// Skipping EMeshPass::TranslucencyAfterDOFModulate because dual blending is not supported on mobile