You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
The uint->float cast was a hack to support old devices with bad drivers. Now it's interfering with mobile preview in DX12, so time to get rid of these hacks. #jira UE-151332 #rb Arciel.Rekman, Dmitriy.Dyomin #preflight 6282d76dc57a894cf6a0f3b4 [CL 20238182 by robert srinivasiah in ue5-main branch]
571 lines
23 KiB
Plaintext
571 lines
23 KiB
Plaintext
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
/*=============================================================================
|
|
MobileBasePassPixelShader.usf: Base pass pixel shader used with forward shading
|
|
=============================================================================*/
|
|
|
|
#include "Common.ush"
|
|
|
|
// Reroute MobileSceneTextures uniform buffer references to the base pass uniform buffer
|
|
#define MobileSceneTextures MobileBasePass.SceneTextures
|
|
#define EyeAdaptationStruct MobileBasePass
|
|
|
|
#define ForwardLightData MobileBasePass.Forward
|
|
#define ReflectionStruct MobileBasePass.ReflectionsParameters
|
|
|
|
#ifndef MOBILE_QL_FORCE_DISABLE_PREINTEGRATEDGF
|
|
#define MOBILE_QL_FORCE_DISABLE_PREINTEGRATEDGF 0
|
|
#endif
|
|
|
|
#define FORWARDSHADING_USE_HQ_ENV_BRDF (MATERIAL_USE_PREINTEGRATED_GF && !MOBILE_QL_FORCE_DISABLE_PREINTEGRATEDGF)
|
|
|
|
//use preintegrated GF lut for simple IBL
|
|
#if FORWARDSHADING_USE_HQ_ENV_BRDF
|
|
#define PreIntegratedGF MobileBasePass.PreIntegratedGFTexture
|
|
#define PreIntegratedGFSampler MobileBasePass.PreIntegratedGFSampler
|
|
#endif
|
|
|
|
#define APPLY_AO 0
|
|
|
|
#if (MATERIALBLENDING_MASKED || MATERIALBLENDING_SOLID)
|
|
#if ENABLE_AMBIENT_OCCLUSION && !MATERIAL_SHADINGMODEL_UNLIT
|
|
#undef APPLY_AO
|
|
#define APPLY_AO 1
|
|
#endif
|
|
#endif
|
|
|
|
#if APPLY_AO
|
|
#define AmbientOcclusionTexture MobileBasePass.AmbientOcclusionTexture
|
|
#define AmbientOcclusionSampler MobileBasePass.AmbientOcclusionSampler
|
|
#define AmbientOcclusionStaticFraction MobileBasePass.AmbientOcclusionStaticFraction
|
|
#endif
|
|
|
|
#if MATERIAL_SHADINGMODEL_SINGLELAYERWATER
|
|
#define SIMPLE_SINGLE_LAYER_WATER 1
|
|
#endif
|
|
|
|
#ifndef PROJECT_MOBILE_ENABLE_MOVABLE_SPOTLIGHT_SHADOWS
|
|
#define PROJECT_MOBILE_ENABLE_MOVABLE_SPOTLIGHT_SHADOWS 0
|
|
#endif
|
|
|
|
#ifndef MOBILE_QL_FORCE_FULLY_ROUGH
|
|
#define MOBILE_QL_FORCE_FULLY_ROUGH 0
|
|
#endif
|
|
#ifndef MOBILE_QL_FORCE_NONMETAL
|
|
#define MOBILE_QL_FORCE_NONMETAL 0
|
|
#endif
|
|
#ifndef MOBILE_QL_DISABLE_MATERIAL_NORMAL
|
|
#define MOBILE_QL_DISABLE_MATERIAL_NORMAL 0
|
|
#endif
|
|
|
|
#define FULLY_ROUGH (MATERIAL_FULLY_ROUGH || MOBILE_QL_FORCE_FULLY_ROUGH)
|
|
#define NONMETAL (MATERIAL_NONMETAL || MOBILE_QL_FORCE_NONMETAL)
|
|
#define FORCE_VERTEX_NORMAL (MOBILE_QL_DISABLE_MATERIAL_NORMAL)
|
|
#define SUPPORT_SPOTLIGHTS_SHADOW (MATERIALBLENDING_SOLID || MATERIALBLENDING_MASKED) && PROJECT_MOBILE_ENABLE_MOVABLE_SPOTLIGHT_SHADOWS
|
|
#define DEFERRED_SHADING_PATH (MOBILE_DEFERRED_SHADING && ((MATERIALBLENDING_SOLID || MATERIALBLENDING_MASKED) && !MATERIAL_SHADINGMODEL_SINGLELAYERWATER))
|
|
|
|
// SceneDepthAux always enabled for IOS, on other platforms only enabled when in forward and MobileHDR=true
|
|
#define USE_SCENE_DEPTH_AUX ((METAL_PROFILE || (!DEFERRED_SHADING_PATH && OUTPUT_MOBILE_HDR) || (DEFERRED_SHADING_PATH && USE_GLES_FBF_DEFERRED)) && (MATERIALBLENDING_SOLID || MATERIALBLENDING_MASKED) && !COMPILER_SWITCH)
|
|
|
|
#if DEFERRED_SHADING_PATH && MOBILE_EXTENDED_GBUFFER
|
|
#define SV_TargetDepthAux SV_Target5
|
|
#elif DEFERRED_SHADING_PATH
|
|
#define SV_TargetDepthAux SV_Target4
|
|
#else
|
|
#define SV_TargetDepthAux SV_Target1
|
|
#endif
|
|
|
|
#define TRANSLUCENCY_NON_DIRECTIONAL (MATERIALBLENDING_ANY_TRANSLUCENT && (TRANSLUCENCY_LIGHTING_VOLUMETRIC_NONDIRECTIONAL || TRANSLUCENCY_LIGHTING_VOLUMETRIC_PERVERTEX_NONDIRECTIONAL) && !MATERIAL_SHADINGMODEL_SINGLELAYERWATER)
|
|
|
|
#include "SHCommon.ush"
|
|
#include "/Engine/Generated/Material.ush"
|
|
#include "MobileBasePassCommon.ush"
|
|
#include "/Engine/Generated/VertexFactory.ush"
|
|
#include "LightmapCommon.ush"
|
|
#include "MobileLightingCommon.ush"
|
|
#include "ShadingModelsMaterial.ush"
|
|
|
|
#if MATERIAL_SHADINGMODEL_SINGLELAYERWATER
|
|
#include "SingleLayerWaterShading.ush"
|
|
#endif
|
|
|
|
half3 FrameBufferBlendOp(half4 Source)
|
|
{
|
|
half4 Dest = half4 (0,0,0,0);
|
|
|
|
#if MATERIALBLENDING_SOLID
|
|
return Source.rgb;
|
|
#elif MATERIALBLENDING_MASKED
|
|
return Source.rgb;
|
|
// AlphaComposite will set both MATERIALBLENDING_TRANSLUCENT and MATERIALBLENDING_ALPHACOMPOSITE defines
|
|
// so ensure MATERIALBLENDING_ALPHACOMPOSITE gets first in line
|
|
#elif MATERIALBLENDING_ALPHACOMPOSITE
|
|
return Source.rgb + (Dest.rgb*(1.0 - Source.a));
|
|
// AlphaHoldout will set both MATERIALBLENDING_TRANSLUCENT and MATERIALBLENDING_ALPHAHOLDOUT defines
|
|
// so ensure MATERIALBLENDING_ALPHAHOLDOUT gets first in line
|
|
#elif MATERIALBLENDING_ALPHAHOLDOUT
|
|
return (Dest.rgb*(1.0 - Source.a));
|
|
#elif MATERIALBLENDING_TRANSLUCENT
|
|
return (Source.rgb*Source.a) + (Dest.rgb*(1.0 - Source.a));
|
|
#elif MATERIALBLENDING_ADDITIVE
|
|
return Source.rgb + Dest.rgb;
|
|
#elif MATERIALBLENDING_MODULATE
|
|
return Source.rgb * Dest.rgb;
|
|
#endif
|
|
}
|
|
|
|
void ApplyPixelDepthOffsetForMobileBasePass(inout FMaterialPixelParameters MaterialParameters, FPixelMaterialInputs PixelMaterialInputs, out float OutDepth)
|
|
{
|
|
float PixelDepthOffset = ApplyPixelDepthOffsetToMaterialParameters(MaterialParameters, PixelMaterialInputs, OutDepth);
|
|
}
|
|
|
|
// Force early depth_stencil for non-masked material that use VT feedback
|
|
#if (NUM_VIRTUALTEXTURE_SAMPLES || LIGHTMAP_VT_ENABLED) && !(MATERIALBLENDING_MASKED || USE_DITHERED_LOD_TRANSITION || OUTPUT_PIXEL_DEPTH_OFFSET)
|
|
#define PIXELSHADER_EARLYDEPTHSTENCIL EARLYDEPTHSTENCIL
|
|
#else
|
|
#define PIXELSHADER_EARLYDEPTHSTENCIL
|
|
#endif
|
|
|
|
void ComputeIndirect(VTPageTableResult LightmapVTPageTableResult, FVertexFactoryInterpolantsVSToPS Interpolants, float3 DiffuseDir, half3 DiffuseColorForIndirect, half MaterialAO, out half IndirectIrradiance, inout FMobileLightAccumulator MobileLightAccumulator)
|
|
{
|
|
//To keep IndirectLightingCache conherence with PC, initialize the IndirectIrradiance to zero.
|
|
IndirectIrradiance = 0;
|
|
half3 IndirectColor = 0;
|
|
|
|
// Indirect Diffuse
|
|
#if LQ_TEXTURE_LIGHTMAP
|
|
float2 LightmapUV0, LightmapUV1;
|
|
uint LightmapDataIndex;
|
|
GetLightMapCoordinates(Interpolants, LightmapUV0, LightmapUV1, LightmapDataIndex);
|
|
|
|
half4 LightmapColor = GetLightMapColorLQ(LightmapVTPageTableResult, LightmapUV0, LightmapUV1, LightmapDataIndex, DiffuseDir);
|
|
IndirectColor += LightmapColor.rgb * DiffuseColorForIndirect * View.IndirectLightingColorScale;
|
|
IndirectIrradiance = LightmapColor.a;
|
|
#elif CACHED_POINT_INDIRECT_LIGHTING
|
|
#if MATERIALBLENDING_MASKED || MATERIALBLENDING_SOLID
|
|
// Take the normal into account for opaque
|
|
FThreeBandSHVectorRGB PointIndirectLighting;
|
|
PointIndirectLighting.R.V0 = IndirectLightingCache.IndirectLightingSHCoefficients0[0];
|
|
PointIndirectLighting.R.V1 = IndirectLightingCache.IndirectLightingSHCoefficients1[0];
|
|
PointIndirectLighting.R.V2 = IndirectLightingCache.IndirectLightingSHCoefficients2[0];
|
|
|
|
PointIndirectLighting.G.V0 = IndirectLightingCache.IndirectLightingSHCoefficients0[1];
|
|
PointIndirectLighting.G.V1 = IndirectLightingCache.IndirectLightingSHCoefficients1[1];
|
|
PointIndirectLighting.G.V2 = IndirectLightingCache.IndirectLightingSHCoefficients2[1];
|
|
|
|
PointIndirectLighting.B.V0 = IndirectLightingCache.IndirectLightingSHCoefficients0[2];
|
|
PointIndirectLighting.B.V1 = IndirectLightingCache.IndirectLightingSHCoefficients1[2];
|
|
PointIndirectLighting.B.V2 = IndirectLightingCache.IndirectLightingSHCoefficients2[2];
|
|
|
|
FThreeBandSHVector DiffuseTransferSH = CalcDiffuseTransferSH3(DiffuseDir, 1);
|
|
|
|
// Compute diffuse lighting which takes the normal into account
|
|
half3 DiffuseGI = max(half3(0, 0, 0), DotSH3(PointIndirectLighting, DiffuseTransferSH));
|
|
|
|
IndirectIrradiance = Luminance(DiffuseGI);
|
|
IndirectColor += DiffuseColorForIndirect * DiffuseGI * View.IndirectLightingColorScale;
|
|
#else
|
|
// Non-directional for translucency
|
|
// Ambient terms packed in xyz
|
|
// Already divided by PI and SH ambient on CPU
|
|
half3 PointIndirectLighting = IndirectLightingCache.IndirectLightingSHSingleCoefficient.rgb;
|
|
half3 DiffuseGI = PointIndirectLighting;
|
|
|
|
IndirectIrradiance = Luminance(DiffuseGI);
|
|
IndirectColor += DiffuseColorForIndirect * DiffuseGI * View.IndirectLightingColorScale;
|
|
#endif
|
|
#endif
|
|
IndirectIrradiance *= MaterialAO;
|
|
|
|
MobileLightAccumulator_Add(MobileLightAccumulator, IndirectColor, 0.0f, MaterialAO);
|
|
}
|
|
|
|
PIXELSHADER_EARLYDEPTHSTENCIL
|
|
void Main(
|
|
FVertexFactoryInterpolantsVSToPS Interpolants
|
|
, FMobileBasePassInterpolantsVSToPS BasePassInterpolants
|
|
, in float4 SvPosition : SV_Position
|
|
OPTIONAL_IsFrontFace
|
|
#if DEFERRED_SHADING_PATH
|
|
#if USE_GLES_FBF_DEFERRED
|
|
, out HALF4_TYPE OutProxy : SV_Target0
|
|
#else
|
|
, out HALF4_TYPE OutColor : SV_Target0
|
|
#endif
|
|
, out HALF4_TYPE OutGBufferA : SV_Target1
|
|
, out HALF4_TYPE OutGBufferB : SV_Target2
|
|
, out HALF4_TYPE OutGBufferC : SV_Target3
|
|
#if MOBILE_EXTENDED_GBUFFER
|
|
, out HALF4_TYPE OutGBufferD : SV_Target4
|
|
#endif
|
|
#else
|
|
, out HALF4_TYPE OutColor : SV_Target0
|
|
#endif
|
|
#if USE_SCENE_DEPTH_AUX
|
|
, out float OutSceneDepthAux : SV_TargetDepthAux
|
|
#endif
|
|
#if OUTPUT_PIXEL_DEPTH_OFFSET
|
|
, out float OutDepth : SV_Depth
|
|
#endif
|
|
)
|
|
{
|
|
#if DEFERRED_SHADING_PATH
|
|
#if USE_GLES_FBF_DEFERRED
|
|
half4 OutColor;
|
|
#endif
|
|
#if !MOBILE_EXTENDED_GBUFFER
|
|
half4 OutGBufferD;
|
|
#endif
|
|
#endif
|
|
|
|
#if MOBILE_MULTI_VIEW
|
|
ResolvedView = ResolveView(BasePassInterpolants.MultiViewId);
|
|
#else
|
|
ResolvedView = ResolveView();
|
|
#endif
|
|
|
|
#if USE_GLOBAL_CLIP_PLANE
|
|
clip(BasePassInterpolants.OutClipDistance);
|
|
#endif
|
|
|
|
#if PACK_INTERPOLANTS
|
|
float4 PackedInterpolants[NUM_VF_PACKED_INTERPOLANTS];
|
|
VertexFactoryUnpackInterpolants(Interpolants, PackedInterpolants);
|
|
#endif
|
|
|
|
#if COMPILER_GLSL_ES3_1 && !OUTPUT_MOBILE_HDR && !MOBILE_EMULATION
|
|
// LDR Mobile needs screen vertical flipped
|
|
SvPosition.y = ResolvedView.BufferSizeAndInvSize.y - SvPosition.y - 1;
|
|
#endif
|
|
|
|
FMaterialPixelParameters MaterialParameters = GetMaterialPixelParameters(Interpolants, SvPosition);
|
|
FPixelMaterialInputs PixelMaterialInputs;
|
|
{
|
|
float4 ScreenPosition = SvPositionToResolvedScreenPosition(SvPosition);
|
|
float3 WorldPosition = BasePassInterpolants.PixelPosition.xyz;
|
|
float3 WorldPositionExcludingWPO = BasePassInterpolants.PixelPosition.xyz;
|
|
#if USE_WORLD_POSITION_EXCLUDING_SHADER_OFFSETS
|
|
WorldPositionExcludingWPO = BasePassInterpolants.PixelPositionExcludingWPO;
|
|
#endif
|
|
CalcMaterialParametersEx(MaterialParameters, PixelMaterialInputs, SvPosition, ScreenPosition, bIsFrontFace, WorldPosition, WorldPositionExcludingWPO);
|
|
|
|
#if FORCE_VERTEX_NORMAL
|
|
// Quality level override of material's normal calculation, can be used to avoid normal map reads etc.
|
|
MaterialParameters.WorldNormal = MaterialParameters.TangentToWorld[2];
|
|
MaterialParameters.ReflectionVector = ReflectionAboutCustomWorldNormal(MaterialParameters, MaterialParameters.WorldNormal, false);
|
|
#endif
|
|
}
|
|
|
|
#if OUTPUT_PIXEL_DEPTH_OFFSET
|
|
ApplyPixelDepthOffsetForMobileBasePass(MaterialParameters, PixelMaterialInputs, OutDepth);
|
|
#endif
|
|
|
|
#if !EARLY_Z_PASS_ONLY_MATERIAL_MASKING
|
|
//Clip if the blend mode requires it.
|
|
GetMaterialCoverageAndClipping(MaterialParameters, PixelMaterialInputs);
|
|
#endif
|
|
|
|
// Store the results in local variables and reuse instead of calling the functions multiple times.
|
|
half3 BaseColor = GetMaterialBaseColor(PixelMaterialInputs);
|
|
half Metallic = GetMaterialMetallic(PixelMaterialInputs);
|
|
half Specular = GetMaterialSpecular(PixelMaterialInputs);
|
|
// The smallest normalized value that can be represented in IEEE 754 (FP16) is 2^-24 = 5.96e-8.
|
|
// The code will make the following computation involving roughness: 1.0 / Roughness^4.
|
|
// Therefore to prevent division by zero on devices that do not support denormals, Roughness^4
|
|
// must be >= 5.96e-8. We will clamp to 0.015625 because 0.015625^4 = 5.96e-8.
|
|
//
|
|
// Note that we also clamp to 1.0 to match the deferred renderer on PC where the roughness is
|
|
// stored in an 8-bit value and thus automatically clamped at 1.0.
|
|
half Roughness = max(0.015625f, GetMaterialRoughness(PixelMaterialInputs));
|
|
half Anisotropy = GetMaterialAnisotropy(PixelMaterialInputs);
|
|
uint ShadingModelID = GetMaterialShadingModel(PixelMaterialInputs);
|
|
half Opacity = GetMaterialOpacity(PixelMaterialInputs);
|
|
half MaterialAO = GetMaterialAmbientOcclusion(PixelMaterialInputs);
|
|
|
|
// If we don't use this shading model the color should be black (don't generate shader code for unused data, don't do indirectlighting cache lighting with this color).
|
|
float3 SubsurfaceColor = 0;
|
|
// 0..1, SubsurfaceProfileId = int(x * 255)
|
|
float SubsurfaceProfile = 0;
|
|
|
|
#if (MATERIAL_SHADINGMODEL_SUBSURFACE || MATERIAL_SHADINGMODEL_PREINTEGRATED_SKIN || MATERIAL_SHADINGMODEL_SUBSURFACE_PROFILE) && MOBILE_SHADINGMODEL_SUPPORT
|
|
half4 SubsurfaceData = GetMaterialSubsurfaceData(PixelMaterialInputs);
|
|
|
|
SubsurfaceColor = SubsurfaceData.rgb * ResolvedView.DiffuseOverrideParameter.w + ResolvedView.DiffuseOverrideParameter.xyz;
|
|
|
|
SubsurfaceProfile = SubsurfaceData.a;
|
|
#endif
|
|
|
|
#if APPLY_AO
|
|
half4 GatheredAmbientOcclusion = Texture2DSample(AmbientOcclusionTexture, AmbientOcclusionSampler, SvPositionToBufferUV(SvPosition));
|
|
|
|
MaterialAO *= GatheredAmbientOcclusion.r;
|
|
#endif
|
|
|
|
FGBufferData GBuffer = (FGBufferData)0;
|
|
GBuffer.GBufferAO = MaterialAO;
|
|
GBuffer.Depth = MaterialParameters.ScreenPosition.w;
|
|
|
|
SetGBufferForShadingModel(
|
|
GBuffer,
|
|
MaterialParameters,
|
|
Opacity,
|
|
BaseColor,
|
|
Metallic,
|
|
Specular,
|
|
Roughness,
|
|
Anisotropy,
|
|
SubsurfaceColor,
|
|
SubsurfaceProfile,
|
|
0.0f,
|
|
ShadingModelID
|
|
);
|
|
|
|
GBuffer.Roughness = max(0.015625f, GBuffer.Roughness);
|
|
|
|
FMobileShadingModelContext ShadingModelContext = (FMobileShadingModelContext)0;
|
|
ShadingModelContext.Opacity = Opacity;
|
|
|
|
#if MATERIAL_SHADINGMODEL_THIN_TRANSLUCENT
|
|
float TopMaterialCoverage = ShadingModelContext.Opacity;
|
|
|
|
// Adjust Opacity
|
|
{
|
|
float3 TransmittanceColor = GetThinTranslucentMaterialOutput0(MaterialParameters);
|
|
float Transmittance = dot(TransmittanceColor, float3(1.0f,1.0f,1.0f)/3.0f);
|
|
|
|
// We can't use the NoV from the shading models because it uses saturate(), whereas we are using abs().
|
|
// The length through the surface is the same for both front and back faces.
|
|
float NoV = abs(dot(MaterialParameters.WorldNormal, MaterialParameters.CameraVector));
|
|
float PathLength = rcp(max(NoV, 1e-5f));
|
|
float NegativeAbsorptionCoefficient = log(Transmittance);
|
|
|
|
// Material Modulation is how much of the background light goes through the surface
|
|
float MaterialModulation = exp(NegativeAbsorptionCoefficient * PathLength);
|
|
|
|
// The alpha of the material in translucent mode is one minus the amount that it is modulating the background by.
|
|
float MaterialOpacity = 1.0f - MaterialModulation;
|
|
|
|
ShadingModelContext.Opacity = 1.0f - (1.0f - TopMaterialCoverage) * (1.0f - MaterialOpacity);
|
|
}
|
|
|
|
GBuffer.BaseColor *= TopMaterialCoverage;
|
|
#endif
|
|
|
|
#if MATERIAL_SHADINGMODEL_SUBSURFACE_PROFILE && MOBILE_SHADINGMODEL_SUPPORT
|
|
if (GBuffer.ShadingModelID == SHADINGMODELID_SUBSURFACE_PROFILE)
|
|
{
|
|
#if MATERIAL_SUBSURFACE_PROFILE_USE_CURVATURE
|
|
GBuffer.CustomData.g = GetMaterialCustomData0(MaterialParameters);
|
|
#else
|
|
GBuffer.CustomData.g = CalculateCurvature(GBuffer.WorldNormal, MaterialParameters.WorldPosition_CamRelative);
|
|
#endif
|
|
|
|
GBuffer.CustomData.g = max(saturate(GBuffer.CustomData.g), 0.001f);
|
|
}
|
|
#endif
|
|
InitShadingModelContext(ShadingModelContext, GBuffer, MaterialParameters.CameraVector);
|
|
|
|
VTPageTableResult LightmapVTPageTableResult = (VTPageTableResult)0.0f;
|
|
#if LIGHTMAP_VT_ENABLED
|
|
{
|
|
float2 LightmapUV0, LightmapUV1;
|
|
uint LightmapDataIndex;
|
|
GetLightMapCoordinates(Interpolants, LightmapUV0, LightmapUV1, LightmapDataIndex);
|
|
LightmapVTPageTableResult = LightmapGetVTSampleInfo(LightmapUV0, LightmapDataIndex, SvPosition.xy);
|
|
}
|
|
#endif
|
|
|
|
#if LIGHTMAP_VT_ENABLED
|
|
// This must occur after CalcMaterialParameters(), which is required to initialize the VT feedback mechanism
|
|
// Lightmap request is always the first VT sample in the shader
|
|
StoreVirtualTextureFeedback(MaterialParameters.VirtualTextureFeedback, 0, LightmapVTPageTableResult.PackedRequest);
|
|
#endif
|
|
|
|
FMobileLightAccumulator MobileLightAccumulator = (FMobileLightAccumulator)0;
|
|
|
|
half IndirectIrradiance;
|
|
half3 IndirectColor;
|
|
half3 DiffuseColorForIndirect = ShadingModelContext.DiffuseColor;
|
|
|
|
#if (MATERIAL_SHADINGMODEL_SUBSURFACE || MATERIAL_SHADINGMODEL_PREINTEGRATED_SKIN) && MOBILE_SHADINGMODEL_SUPPORT
|
|
if (GBuffer.ShadingModelID == SHADINGMODELID_SUBSURFACE || GBuffer.ShadingModelID == SHADINGMODELID_PREINTEGRATED_SKIN)
|
|
{
|
|
DiffuseColorForIndirect += ShadingModelContext.SubsurfaceColor;
|
|
}
|
|
#endif
|
|
|
|
// Apply MaterialAO since we don't have the DiffuseIndirectComposite pass on mobile deferred.
|
|
ComputeIndirect(LightmapVTPageTableResult, Interpolants, ShadingModelContext.DiffuseDir, DiffuseColorForIndirect, MaterialAO, IndirectIrradiance, MobileLightAccumulator);
|
|
|
|
half Shadow = GetPrimaryPrecomputedShadowMask(LightmapVTPageTableResult, Interpolants, MaterialParameters).r;
|
|
|
|
#if DEFERRED_SHADING_PATH
|
|
GBuffer.IndirectIrradiance = IndirectIrradiance;
|
|
GBuffer.PrecomputedShadowFactors.r = Shadow;
|
|
MobileEncodeGBuffer(GBuffer, OutGBufferA, OutGBufferB, OutGBufferC, OutGBufferD);
|
|
#else
|
|
|
|
half4 DynamicShadowFactors = 1.0f;
|
|
half NoL = 0.0f;
|
|
|
|
// Directional light
|
|
AccumulateDirectionalLighting(GBuffer, ShadingModelContext, MaterialParameters.CameraVector, MaterialParameters.ScreenPosition, SvPosition, Shadow, DynamicShadowFactors, NoL, MobileLightAccumulator);
|
|
|
|
// Skylight
|
|
bool bApplySkyLighting = !(MATERIAL_TWOSIDED && LQ_TEXTURE_LIGHTMAP) || NoL == 0;
|
|
AccumulateSkyLighting(GBuffer, ShadingModelContext, ResolvedView.SkyLightColor.rgb, bApplySkyLighting, IndirectIrradiance, MobileLightAccumulator);
|
|
|
|
float2 LocalPosition = SvPosition.xy - ResolvedView.ViewRectMin.xy;
|
|
uint GridIndex = ComputeLightGridCellIndex(uint2(LocalPosition.x, LocalPosition.y), SvPosition.w);
|
|
|
|
// Reflection IBL
|
|
#if !(MATERIAL_SINGLE_SHADINGMODEL && MATERIAL_SHADINGMODEL_HAIR)
|
|
AccumulateReflection(GBuffer
|
|
, ShadingModelContext
|
|
, MaterialParameters.WorldPosition_CamRelative
|
|
, MaterialParameters.ReflectionVector
|
|
, IndirectIrradiance
|
|
, GridIndex
|
|
, MobileLightAccumulator);
|
|
#endif
|
|
|
|
// Local lights
|
|
#if !MATERIAL_SHADINGMODEL_SINGLELAYERWATER && ENABLE_CLUSTERED_LIGHTS
|
|
{
|
|
const uint EyeIndex = 0;
|
|
const FCulledLightsGridData CulledLightGridData = GetCulledLightsGrid(GridIndex, EyeIndex);
|
|
half4 LocalLightDynamicShadowFactors = 1.0f;
|
|
|
|
#if USE_SHADOWMASKTEXTURE
|
|
LocalLightDynamicShadowFactors = DynamicShadowFactors;
|
|
#endif
|
|
|
|
uint LightingChannelMask = GetPrimitive_LightingChannelMask(MaterialParameters.PrimitiveId);
|
|
AccumulateLightGridLocalLighting(CulledLightGridData, ShadingModelContext, GBuffer, MaterialParameters.WorldPosition_CamRelative, MaterialParameters.CameraVector, EyeIndex, 0, LocalLightDynamicShadowFactors, LightingChannelMask, MobileLightAccumulator);
|
|
}
|
|
#endif
|
|
|
|
#if MATERIAL_SHADINGMODEL_SINGLELAYERWATER
|
|
{
|
|
const bool bSeparateMainDirLightLuminance = false;
|
|
float3 SeparatedWaterMainDirLightLuminance = float3(0, 0, 0);
|
|
|
|
const bool CameraIsUnderWater = false; // Fade out the material contribution over to water contribution according to material opacity.
|
|
const float3 SunIlluminance = ResolvedView.DirectionalLightColor.rgb * PI; // times PI because it is divided by PI on CPU (=luminance) and we want illuminance here.
|
|
const float3 WaterDiffuseIndirectIlluminance = ShadingModelContext.WaterDiffuseIndirectLuminance * PI; // DiffuseIndirectLighting is luminance. So we need to multiply by PI to get illuminance.
|
|
const float3 EnvBrdf = ShadingModelContext.EnvBrdf;
|
|
const uint EyeIndex = 0;
|
|
|
|
const float4 NullDistortionParams = 1.0f;
|
|
WaterVolumeLightingOutput WaterLighting = EvaluateWaterVolumeLighting(
|
|
MaterialParameters, PixelMaterialInputs, ResolvedView,
|
|
Shadow, GBuffer.Specular, NullDistortionParams,
|
|
SunIlluminance, WaterDiffuseIndirectIlluminance, EnvBrdf,
|
|
CameraIsUnderWater, ShadingModelContext.WaterVisibility, EyeIndex,
|
|
bSeparateMainDirLightLuminance, SeparatedWaterMainDirLightLuminance);
|
|
|
|
// Accumulate luminance and occlude the background according to transmittance to view and mean transmittance to lights.
|
|
MobileLightAccumulator_Add(MobileLightAccumulator, WaterLighting.Luminance, 0.0f, 1.0f);
|
|
ShadingModelContext.Opacity = 1.0 - ((1.0 - ShadingModelContext.Opacity) * dot(WaterLighting.WaterToSceneToLightTransmittance, float3(1.0 / 3.0, 1.0 / 3.0, 1.0 / 3.0)));
|
|
}
|
|
#endif // MATERIAL_SHADINGMODEL_SINGLELAYERWATER
|
|
|
|
#endif// DEFERRED_SHADING_PATH
|
|
|
|
#if !MATERIAL_SHADINGMODEL_UNLIT
|
|
half3 Color = MobileLightAccumulator_GetResult(MobileLightAccumulator);
|
|
#else
|
|
half3 Color = 0.0f;
|
|
#endif
|
|
|
|
half4 VertexFog = half4(0, 0, 0, 1);
|
|
|
|
#if USE_VERTEX_FOG
|
|
#if PACK_INTERPOLANTS
|
|
VertexFog = PackedInterpolants[0];
|
|
#else
|
|
VertexFog = BasePassInterpolants.VertexFog;
|
|
#endif
|
|
#endif
|
|
// NEEDS_BASEPASS_PIXEL_FOGGING is not allowed on mobile for the sake of performance.
|
|
|
|
half3 Emissive = GetMaterialEmissive(PixelMaterialInputs);
|
|
#if MATERIAL_SHADINGMODEL_THIN_TRANSLUCENT
|
|
Emissive *= TopMaterialCoverage;
|
|
#endif
|
|
Color += Emissive;
|
|
|
|
#if !MATERIAL_SHADINGMODEL_UNLIT && MOBILE_EMULATION
|
|
Color = lerp(Color, ShadingModelContext.DiffuseColor, ResolvedView.UnlitViewmodeMask);
|
|
#endif
|
|
|
|
// On mobile, water (an opaque material) is rendered as trnaslucent with forced premultiplied alpha blending (see MobileBasePass::SetTranslucentRenderState)
|
|
#if MATERIALBLENDING_ALPHACOMPOSITE || MATERIAL_SHADINGMODEL_SINGLELAYERWATER
|
|
OutColor = half4(Color * VertexFog.a + VertexFog.rgb * ShadingModelContext.Opacity, ShadingModelContext.Opacity);
|
|
#elif MATERIALBLENDING_ALPHAHOLDOUT
|
|
// not implemented for holdout
|
|
OutColor = half4(Color * VertexFog.a + VertexFog.rgb * ShadingModelContext.Opacity, ShadingModelContext.Opacity);
|
|
#elif MATERIALBLENDING_TRANSLUCENT
|
|
OutColor = half4(Color * VertexFog.a + VertexFog.rgb, ShadingModelContext.Opacity);
|
|
#elif MATERIALBLENDING_ADDITIVE
|
|
OutColor = half4(Color * (VertexFog.a * ShadingModelContext.Opacity.x), 0.0f);
|
|
#elif MATERIALBLENDING_MODULATE
|
|
half3 FoggedColor = lerp(half3(1, 1, 1), Color, VertexFog.aaa * VertexFog.aaa);
|
|
OutColor = half4(FoggedColor, ShadingModelContext.Opacity);
|
|
#else
|
|
OutColor.rgb = Color * VertexFog.a + VertexFog.rgb;
|
|
|
|
#if !MATERIAL_USE_ALPHA_TO_COVERAGE
|
|
// Planar reflections and scene captures use scene color alpha to keep track of where content has been rendered, for compositing into a different scene later
|
|
OutColor.a = 0.0;
|
|
#else
|
|
half MaterialOpacityClip = GetMaterialOpacityMaskClipValue();
|
|
float Mask = GetMaterialMask(PixelMaterialInputs) / (1.0 - MaterialOpacityClip);
|
|
OutColor.a = uint((Mask + 0.25f) * 4.0f) / 4.0f;
|
|
#endif
|
|
#endif
|
|
|
|
#if USE_SCENE_DEPTH_AUX
|
|
OutSceneDepthAux = SvPosition.z;
|
|
#endif
|
|
|
|
#if !MATERIALBLENDING_MODULATE
|
|
OutColor.rgb *= ResolvedView.PreExposure;
|
|
#endif
|
|
|
|
#if MATERIAL_IS_SKY
|
|
// Sky materials can result in high luminance values, e.g. the sun disk.
|
|
// This is so we make sure to at least stay within the boundaries of fp10 and not cause NaN on some platforms.
|
|
// We also half that range to also make sure we have room for other additive elements such as bloom, clouds or particle visual effects.
|
|
OutColor.rgb = min(OutColor.rgb, Max10BitsFloat.xxx * 0.5f);
|
|
#endif
|
|
|
|
#if USE_EDITOR_COMPOSITING && (MOBILE_EMULATION)
|
|
// Editor primitive depth testing
|
|
OutColor.a = 1.0;
|
|
#if MATERIALBLENDING_MASKED
|
|
// some material might have an opacity value
|
|
OutColor.a = GetMaterialMaskInputRaw(PixelMaterialInputs);
|
|
#endif
|
|
clip(OutColor.a - GetMaterialOpacityMaskClipValue());
|
|
#else
|
|
#if OUTPUT_GAMMA_SPACE
|
|
OutColor.rgb = sqrt(OutColor.rgb);
|
|
#endif
|
|
#endif
|
|
|
|
#if NUM_VIRTUALTEXTURE_SAMPLES || LIGHTMAP_VT_ENABLED
|
|
FinalizeVirtualTextureFeedback(
|
|
MaterialParameters.VirtualTextureFeedback,
|
|
MaterialParameters.SvPosition,
|
|
ShadingModelContext.Opacity,
|
|
View.FrameNumber,
|
|
View.VTFeedbackBuffer
|
|
);
|
|
#endif
|
|
|
|
#if DEFERRED_SHADING_PATH && USE_GLES_FBF_DEFERRED
|
|
OutProxy.rgb = OutColor.rgb;
|
|
#endif
|
|
}
|