146 lines
6.2 KiB
HLSL
146 lines
6.2 KiB
HLSL
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
/*=============================================================================
|
|
MobileBasePassVertexShader.usf: Base pass vertex shader used with forward shading
|
|
=============================================================================*/
|
|
|
|
#define IS_MOBILE_BASEPASS_VERTEX_SHADER 1
|
|
|
|
#include "Common.ush"
|
|
|
|
// Reroute MobileSceneTextures uniform buffer references to the base pass uniform buffer
|
|
#define MobileSceneTextures MobileBasePass.SceneTextures
|
|
|
|
#include "/Engine/Generated/Material.ush"
|
|
#include "MobileBasePassCommon.ush"
|
|
#include "/Engine/Generated/VertexFactory.ush"
|
|
#include "HeightFogCommon.ush"
|
|
|
|
#if USE_VERTEX_FOG && PROJECT_SUPPORT_SKY_ATMOSPHERE
|
|
#include "SkyAtmosphereCommon.ush"
|
|
#endif
|
|
|
|
#if LOCAL_FOG_VOLUME_ON_TRANSLUCENT
|
|
#include "LocalFogVolumes/LocalFogVolumeCommon.ush"
|
|
#endif
|
|
|
|
struct FMobileShadingBasePassVSToPS
|
|
{
|
|
FVertexFactoryInterpolantsVSToPS FactoryInterpolants;
|
|
FMobileBasePassInterpolantsVSToPS BasePassInterpolants;
|
|
FStereoVSOutput StereoOutput;
|
|
INVARIANT_OUTPUT float4 Position : SV_POSITION;
|
|
};
|
|
|
|
#define FMobileShadingBasePassVSOutput FMobileShadingBasePassVSToPS
|
|
#define VertexFactoryGetInterpolants VertexFactoryGetInterpolantsVSToPS
|
|
|
|
/** Entry point for the base pass vertex shader. */
|
|
void Main(
|
|
FVertexFactoryInput Input,
|
|
out FMobileShadingBasePassVSOutput Output
|
|
)
|
|
{
|
|
StereoSetupVF(Input, Output.StereoOutput);
|
|
const uint EyeIndex = GetEyeIndexFromVF(Input);
|
|
|
|
#if PACK_INTERPOLANTS
|
|
float4 PackedInterps[NUM_VF_PACKED_INTERPOLANTS];
|
|
UNROLL
|
|
for(int i = 0; i < NUM_VF_PACKED_INTERPOLANTS; ++i)
|
|
{
|
|
PackedInterps[i] = 0;
|
|
}
|
|
#endif
|
|
|
|
FVertexFactoryIntermediates VFIntermediates = GetVertexFactoryIntermediates(Input);
|
|
float4 WorldPositionExcludingWPO = VertexFactoryGetWorldPosition(Input, VFIntermediates);
|
|
float4 WorldPosition = WorldPositionExcludingWPO;
|
|
|
|
half3x3 TangentToLocal = VertexFactoryGetTangentToLocal(Input, VFIntermediates);
|
|
FMaterialVertexParameters VertexParameters = GetMaterialVertexParameters(Input, VFIntermediates, WorldPosition.xyz, TangentToLocal);
|
|
|
|
float3 WorldPositionOffset = GetMaterialWorldPositionOffset(VertexParameters);
|
|
|
|
WorldPosition.xyz += WorldPositionOffset;
|
|
|
|
ApplyMaterialFirstPersonTransform(VertexParameters, WorldPosition.xyz);
|
|
|
|
float4 RasterizedWorldPosition = VertexFactoryGetRasterizedWorldPosition(Input, VFIntermediates, WorldPosition);
|
|
Output.Position = INVARIANT(mul(RasterizedWorldPosition, ResolvedView.TranslatedWorldToClip));
|
|
Output.BasePassInterpolants.PixelPosition = WorldPosition;
|
|
|
|
#if USE_WORLD_POSITION_EXCLUDING_SHADER_OFFSETS
|
|
Output.BasePassInterpolants.PixelPositionExcludingWPO = WorldPositionExcludingWPO.xyz;
|
|
#endif
|
|
|
|
#if USE_GLOBAL_CLIP_PLANE
|
|
Output.BasePassInterpolants.OutClipDistance = dot(ResolvedView.GlobalClippingPlane, float4(WorldPosition.xyz, 1));
|
|
#endif
|
|
|
|
#if USE_VERTEX_FOG
|
|
|
|
half4 VertexFog = float4(0, 0, 0, 1);
|
|
if (ResolvedView.RealTimeReflectionCapture == 0.0f)
|
|
{
|
|
// We only render fog on the sky dome per vertex if not rendering a real time reflection capture. A reflection capture have its own fog pass.
|
|
|
|
float3 WorldPositionRelativeToCamera = WorldPosition.xyz - ResolvedView.TranslatedWorldCameraOrigin;
|
|
if (MATERIAL_IS_SKY)
|
|
{
|
|
// If this is a IsSky material, then we evaluated the fog as if it was up to Far DeviceZ. This is to match deferred renderer SkyPass not writting depth.
|
|
WorldPositionRelativeToCamera = normalize(WorldPosition.xyz - ResolvedView.TranslatedWorldCameraOrigin) * ConvertFromDeviceZ(max(1.0e-38, FarDepthValue));
|
|
}
|
|
|
|
VertexFog = CalculateHeightFog(WorldPositionRelativeToCamera, EyeIndex, ResolvedView); // WorldPosition is in fact TranslatedWorldPosition
|
|
}
|
|
|
|
#if PROJECT_SUPPORT_SKY_ATMOSPHERE && MATERIAL_IS_SKY==0 // Do not apply aerial perpsective on sky materials
|
|
if (ResolvedView.SkyAtmosphereApplyCameraAerialPerspectiveVolume > 0.0f)
|
|
{
|
|
// Sample the aerial perspective (AP). It is also blended under the VertexFog parameter.
|
|
VertexFog = GetAerialPerspectiveLuminanceTransmittanceWithFogOver(
|
|
ResolvedView.RealTimeReflectionCapture, ResolvedView.SkyAtmosphereCameraAerialPerspectiveVolumeSizeAndInvSize,
|
|
Output.Position, (WorldPosition.xyz - ResolvedView.TranslatedWorldCameraOrigin) * CM_TO_SKY_UNIT,
|
|
View.CameraAerialPerspectiveVolume, View.CameraAerialPerspectiveVolumeSampler,
|
|
ResolvedView.SkyAtmosphereCameraAerialPerspectiveVolumeDepthResolutionInv,
|
|
ResolvedView.SkyAtmosphereCameraAerialPerspectiveVolumeDepthResolution,
|
|
ResolvedView.SkyAtmosphereAerialPerspectiveStartDepthKm,
|
|
ResolvedView.SkyAtmosphereCameraAerialPerspectiveVolumeDepthSliceLengthKm,
|
|
ResolvedView.SkyAtmosphereCameraAerialPerspectiveVolumeDepthSliceLengthKmInv,
|
|
ResolvedView.OneOverPreExposure, VertexFog);
|
|
}
|
|
#endif
|
|
|
|
// Apply local fog volume if enabled. Note: volumetric fog is not applied on mobile so it can result in visual discrepancy.
|
|
#if LOCAL_FOG_VOLUME_ON_TRANSLUCENT
|
|
float4 VertexClipSpacePosition = mul(float4(WorldPosition.xyz, 1), ResolvedView.TranslatedWorldToClip);
|
|
float2 SvPosition = (VertexClipSpacePosition.xy / VertexClipSpacePosition.w * float2(.5f, -.5f) + .5f) * ResolvedView.ViewSizeAndInvSize.xy;
|
|
uint2 TilePos = clamp(uint2(SvPosition.xy / float(LFVTilePixelSize)), uint2(0, 0), LFVTileDataResolution - 1);
|
|
const bool bPlatformSupportsVolumetricFogOntranslucent = false; // Mobile does not do that so we try to compensate for it by evalauting LFV regularly on translucent.
|
|
float4 LFVContribution = GetLFVContribution(ResolvedView, TilePos, WorldPosition.xyz, bPlatformSupportsVolumetricFogOntranslucent);
|
|
VertexFog = float4(LFVContribution.rgb + VertexFog.rgb * LFVContribution.a, LFVContribution.a * VertexFog.a);
|
|
#endif // LOCAL_FOG_VOLUME_ON_TRANSLUCENT
|
|
|
|
#if PACK_INTERPOLANTS
|
|
PackedInterps[0] = VertexFog;
|
|
#else
|
|
Output.BasePassInterpolants.VertexFog = VertexFog;
|
|
#endif // PACK_INTERPOLANTS
|
|
#endif // USE_VERTEX_FOG
|
|
|
|
#if LANDSCAPE_BUG_WORKAROUND
|
|
Output.BasePassInterpolants.DummyInterp = 0;
|
|
#endif
|
|
|
|
|
|
|
|
Output.FactoryInterpolants = VertexFactoryGetInterpolants(Input, VFIntermediates, VertexParameters);
|
|
|
|
Output.BasePassInterpolants.PixelPosition.w = Output.Position.w;
|
|
|
|
#if PACK_INTERPOLANTS
|
|
VertexFactoryPackInterpolants(Output.FactoryInterpolants, PackedInterps);
|
|
#endif // PACK_INTERPOLANTS
|
|
}
|