249 lines
12 KiB
HLSL
249 lines
12 KiB
HLSL
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
/*=============================================================================
|
|
BasePassVertexShader.usf: Base pass vertex shader
|
|
=============================================================================*/
|
|
|
|
#include "BasePassVertexCommon.ush"
|
|
#include "SHCommon.ush"
|
|
#include "VolumetricLightmapShared.ush"
|
|
|
|
#if TRANSLUCENCY_PERVERTEX_FORWARD_SHADING
|
|
#include "ReflectionEnvironmentShared.ush"
|
|
|
|
// Enables applying a cloud shadow factor to lighting calculations in ForwardLightingCommon.ush.
|
|
#define ENABLE_FORWARD_CLOUD_SHADOW SUPPORT_CLOUD_SHADOW_ON_FORWARD_LIT_TRANSLUCENT
|
|
#include "ForwardLightingCommon.ush"
|
|
#endif
|
|
|
|
#if NEEDS_BASEPASS_VERTEX_FOGGING && PROJECT_SUPPORT_SKY_ATMOSPHERE
|
|
#include "SkyAtmosphereCommon.ush"
|
|
#endif
|
|
|
|
#if (NEEDS_BASEPASS_VERTEX_FOGGING && MATERIAL_ENABLE_TRANSLUCENCY_CLOUD_FOGGING) || SUPPORT_CLOUD_SHADOW_ON_FORWARD_LIT_TRANSLUCENT || NEEDS_BASEPASS_CLOUD_SHADOW_INTERPOLATOR
|
|
#include "VolumetricCloudCommon.ush"
|
|
#endif
|
|
|
|
#if LOCAL_FOG_VOLUME_ON_TRANSLUCENT
|
|
#include "LocalFogVolumes/LocalFogVolumeCommon.ush"
|
|
#endif
|
|
|
|
/** Entry point for the base pass vertex shader. */
|
|
void Main(
|
|
FVertexFactoryInput Input,
|
|
out FBasePassVSOutput Output
|
|
#if USE_GLOBAL_CLIP_PLANE
|
|
, out float OutGlobalClipPlaneDistance : SV_ClipDistance
|
|
#endif
|
|
)
|
|
{
|
|
StereoSetupVF(Input, Output.StereoOutput);
|
|
const uint EyeIndex = GetEyeIndexFromVF(Input);
|
|
|
|
FVertexFactoryIntermediates VFIntermediates = GetVertexFactoryIntermediates(Input);
|
|
float4 WorldPositionExcludingWPO = VertexFactoryGetWorldPosition(Input, VFIntermediates);
|
|
float4 WorldPosition = WorldPositionExcludingWPO;
|
|
float4 ClipSpacePosition;
|
|
|
|
float3x3 TangentToLocal = VertexFactoryGetTangentToLocal(Input, VFIntermediates);
|
|
FMaterialVertexParameters VertexParameters = GetMaterialVertexParameters(Input, VFIntermediates, WorldPosition.xyz, TangentToLocal);
|
|
|
|
// Isolate instructions used for world position offset
|
|
// As these cause the optimizer to generate different position calculating instructions in each pass, resulting in self-z-fighting.
|
|
// This is only necessary for shaders used in passes that have depth testing enabled.
|
|
{
|
|
WorldPosition.xyz += GetMaterialWorldPositionOffset(VertexParameters);
|
|
ApplyMaterialFirstPersonTransform(VertexParameters, WorldPosition.xyz);
|
|
}
|
|
|
|
{
|
|
float4 RasterizedWorldPosition = VertexFactoryGetRasterizedWorldPosition(Input, VFIntermediates, WorldPosition);
|
|
ClipSpacePosition = mul(RasterizedWorldPosition, ResolvedView.TranslatedWorldToClip);
|
|
#if MATERIAL_IS_SKY
|
|
if (IsOrthoProjection())
|
|
{
|
|
//Ortho rendering doesn't stretch to LWC typically, so clamp the sky to as close to the reverse-z far plane as possible unless the dome is already closer to the camera.
|
|
if(ConvertFromDeviceZ(ClipSpacePosition.z) > ResolvedView.OrthoFarPlane)
|
|
{
|
|
ClipSpacePosition.z = FarDepthValue;
|
|
}
|
|
}
|
|
#endif
|
|
Output.Position = INVARIANT(ClipSpacePosition);
|
|
}
|
|
|
|
#if USE_GLOBAL_CLIP_PLANE
|
|
OutGlobalClipPlaneDistance = dot(ResolvedView.GlobalClippingPlane, float4(WorldPosition.xyz, 1));
|
|
#endif
|
|
#if USE_WORLD_POSITION_EXCLUDING_SHADER_OFFSETS
|
|
Output.BasePassInterpolants.PixelPositionExcludingWPO = WorldPositionExcludingWPO.xyz;
|
|
#endif
|
|
|
|
Output.FactoryInterpolants = VertexFactoryGetInterpolants(Input, VFIntermediates, VertexParameters);
|
|
|
|
// Calculate the fog needed for translucency
|
|
#if NEEDS_BASEPASS_VERTEX_FOGGING
|
|
Output.BasePassInterpolants.VertexFog = CalculateHeightFog(WorldPosition.xyz - ResolvedView.TranslatedWorldCameraOrigin, EyeIndex, ResolvedView); // WorldPosition is in fact TranslatedWorldPosition
|
|
|
|
const float OneOverPreExposure = ResolvedView.OneOverPreExposure;
|
|
|
|
#if PROJECT_SUPPORT_SKY_ATMOSPHERE && BASEPASS_SKYATMOSPHERE_AERIALPERSPECTIVE && 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.
|
|
Output.BasePassInterpolants.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,
|
|
OneOverPreExposure, Output.BasePassInterpolants.VertexFog);
|
|
}
|
|
#endif
|
|
#endif // NEEDS_BASEPASS_VERTEX_FOGGING
|
|
|
|
#if NEEDS_BASEPASS_VERTEX_FOGGING
|
|
|
|
// Apply local fog volume to if enabled. It is always enabled per vertex as of today, that is why it is out ofr the NEEDS_BASEPASS_VERTEX_FOGGING defines.
|
|
#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);
|
|
float4 LFVContribution = GetLFVContribution(ResolvedView, TilePos, WorldPosition.xyz);
|
|
Output.BasePassInterpolants.VertexFog = float4(LFVContribution.rgb + Output.BasePassInterpolants.VertexFog.rgb * LFVContribution.a, LFVContribution.a * Output.BasePassInterpolants.VertexFog.a);
|
|
#endif // LOCAL_FOG_VOLUME_ON_TRANSLUCENT
|
|
|
|
#if MATERIAL_ENABLE_TRANSLUCENCY_CLOUD_FOGGING
|
|
if (TranslucentBasePass.ApplyVolumetricCloudOnTransparent > 0.0f)
|
|
{
|
|
Output.BasePassInterpolants.VertexFog = GetCloudLuminanceTransmittanceOverFog(
|
|
Output.Position, WorldPosition.xyz, ResolvedView.TranslatedWorldCameraOrigin,
|
|
TranslucentBasePass.VolumetricCloudColor, TranslucentBasePass.VolumetricCloudColorSampler,
|
|
TranslucentBasePass.VolumetricCloudDepth, TranslucentBasePass.VolumetricCloudDepthSampler,
|
|
OneOverPreExposure, Output.BasePassInterpolants.VertexFog, TranslucentBasePass.SoftBlendingDistanceKm,
|
|
TranslucentBasePass.VolumetricCloudColorUVScale, TranslucentBasePass.VolumetricCloudColorUVMax);
|
|
}
|
|
#endif
|
|
|
|
#endif // NEEDS_BASEPASS_VERTEX_FOGGING
|
|
|
|
#if TRANSLUCENCY_ANY_PERVERTEX_LIGHTING || SUPPORT_CLOUD_SHADOW_ON_FORWARD_LIT_TRANSLUCENT || NEEDS_BASEPASS_CLOUD_SHADOW_INTERPOLATOR
|
|
float3 WorldPositionForVertexLightingTranslated = VertexFactoryGetPositionForVertexLighting(Input, VFIntermediates, WorldPosition.xyz);
|
|
float3 WorldPositionForVertexLighting = WorldPositionForVertexLightingTranslated - DFHackToFloat(ResolvedView.PreViewTranslation);
|
|
#endif
|
|
|
|
#if TRANSLUCENCY_PERVERTEX_LIGHTING_VOLUME
|
|
float4 VolumeLighting;
|
|
float3 InterpolatedLighting = 0;
|
|
|
|
float3 InnerVolumeUVs;
|
|
float3 OuterVolumeUVs;
|
|
float FinalLerpFactor;
|
|
|
|
//@todo - get from VF
|
|
float3 LightingPositionOffset = 0;
|
|
ComputeVolumeUVs(WorldPositionForVertexLightingTranslated, LightingPositionOffset, InnerVolumeUVs, OuterVolumeUVs, FinalLerpFactor);
|
|
|
|
#if TRANSLUCENCY_LIGHTING_VOLUMETRIC_PERVERTEX_DIRECTIONAL
|
|
|
|
Output.BasePassInterpolants.AmbientLightingVector = GetAmbientLightingVectorFromTranslucentLightingVolume(InnerVolumeUVs, OuterVolumeUVs, FinalLerpFactor).xyz;
|
|
Output.BasePassInterpolants.DirectionalLightingVector = GetDirectionalLightingVectorFromTranslucentLightingVolume(InnerVolumeUVs, OuterVolumeUVs, FinalLerpFactor);
|
|
|
|
#elif TRANSLUCENCY_LIGHTING_VOLUMETRIC_PERVERTEX_NONDIRECTIONAL
|
|
|
|
Output.BasePassInterpolants.AmbientLightingVector = GetAmbientLightingVectorFromTranslucentLightingVolume(InnerVolumeUVs, OuterVolumeUVs, FinalLerpFactor).xyz;
|
|
|
|
#endif
|
|
#elif TRANSLUCENCY_PERVERTEX_FORWARD_SHADING
|
|
|
|
float4 VertexLightingClipSpacePosition = mul(float4(WorldPositionForVertexLightingTranslated, 1), ResolvedView.TranslatedWorldToClip);
|
|
float2 SvPosition = (VertexLightingClipSpacePosition.xy / VertexLightingClipSpacePosition.w * float2(.5f, -.5f) + .5f) * ResolvedView.ViewSizeAndInvSize.xy;
|
|
uint GridIndex = ComputeLightGridCellIndex((uint2)(SvPosition* View.LightProbeSizeRatioAndInvSizeRatio.zw - ResolvedView.ViewRectMin.xy), VertexLightingClipSpacePosition.w, EyeIndex);
|
|
|
|
float DirectionalLightCloudShadow = 1.0f;
|
|
#if SUPPORT_CLOUD_SHADOW_ON_FORWARD_LIT_TRANSLUCENT
|
|
float OutOpticalDepth = 0.0f;
|
|
if (TranslucentBasePass.ForwardDirLightCloudShadow.CloudShadowmapStrength > 0.0f)
|
|
{
|
|
DirectionalLightCloudShadow = lerp(
|
|
1.0f,
|
|
GetCloudVolumetricShadow(
|
|
WorldPositionForVertexLightingTranslated,
|
|
TranslucentBasePass.ForwardDirLightCloudShadow.CloudShadowmapTranslatedWorldToLightClipMatrix,
|
|
TranslucentBasePass.ForwardDirLightCloudShadow.CloudShadowmapFarDepthKm,
|
|
TranslucentBasePass.ForwardDirLightCloudShadow.CloudShadowmapTexture,
|
|
TranslucentBasePass.ForwardDirLightCloudShadow.CloudShadowmapSampler,
|
|
OutOpticalDepth),
|
|
TranslucentBasePass.ForwardDirLightCloudShadow.CloudShadowmapStrength);
|
|
}
|
|
#endif
|
|
|
|
Output.BasePassInterpolants.VertexDiffuseLighting = GetForwardDirectLightingForVertexLighting(GridIndex, WorldPositionForVertexLightingTranslated, Output.Position.w, VertexParameters.TangentToWorld[2], EyeIndex, DirectionalLightCloudShadow);
|
|
|
|
#elif NEEDS_BASEPASS_CLOUD_SHADOW_INTERPOLATOR
|
|
|
|
#if MATERIAL_SHADINGMODEL_SINGLELAYERWATER
|
|
#define ForwardDirLightCloudShadowParams SingleLayerWater.ForwardDirLightCloudShadow
|
|
#elif IS_MATERIAL_TRANSLUCENT_AND_LIT
|
|
#define ForwardDirLightCloudShadowParams TranslucentBasePass.ForwardDirLightCloudShadow
|
|
#endif
|
|
|
|
Output.BasePassInterpolants.VertexCloudShadow = 1.0f;
|
|
if (ForwardDirLightCloudShadowParams.CloudShadowmapStrength > 0.0f)
|
|
{
|
|
float OutOpticalDepth = 0.0f;
|
|
Output.BasePassInterpolants.VertexCloudShadow = lerp(
|
|
1.0f,
|
|
GetCloudVolumetricShadow(
|
|
WorldPositionForVertexLightingTranslated,
|
|
ForwardDirLightCloudShadowParams.CloudShadowmapTranslatedWorldToLightClipMatrix,
|
|
ForwardDirLightCloudShadowParams.CloudShadowmapFarDepthKm,
|
|
ForwardDirLightCloudShadowParams.CloudShadowmapTexture,
|
|
ForwardDirLightCloudShadowParams.CloudShadowmapSampler,
|
|
OutOpticalDepth),
|
|
ForwardDirLightCloudShadowParams.CloudShadowmapStrength);
|
|
}
|
|
|
|
#undef ForwardDirLightCloudShadowParams
|
|
|
|
#endif
|
|
|
|
#if PRECOMPUTED_IRRADIANCE_VOLUME_LIGHTING && TRANSLUCENCY_ANY_PERVERTEX_LIGHTING
|
|
float3 BrickTextureUVs = ComputeVolumetricLightmapBrickTextureUVs(WorldPositionForVertexLighting);
|
|
|
|
#if TRANSLUCENCY_LIGHTING_VOLUMETRIC_PERVERTEX_NONDIRECTIONAL
|
|
FOneBandSHVectorRGB IrradianceSH = GetVolumetricLightmapSH1(BrickTextureUVs);
|
|
Output.BasePassInterpolants.VertexIndirectAmbient = float3(IrradianceSH.R.V, IrradianceSH.G.V, IrradianceSH.B.V);
|
|
#elif TRANSLUCENCY_LIGHTING_VOLUMETRIC_PERVERTEX_DIRECTIONAL
|
|
// Need to interpolate directional lighting so we can incorporate a normal in the pixel shader
|
|
FTwoBandSHVectorRGB IrradianceSH = GetVolumetricLightmapSH2(BrickTextureUVs);
|
|
Output.BasePassInterpolants.VertexIndirectSH[0] = IrradianceSH.R.V;
|
|
Output.BasePassInterpolants.VertexIndirectSH[1] = IrradianceSH.G.V;
|
|
Output.BasePassInterpolants.VertexIndirectSH[2] = IrradianceSH.B.V;
|
|
#endif
|
|
#endif
|
|
|
|
#if WRITES_VELOCITY_TO_GBUFFER
|
|
{
|
|
float4 PrevTranslatedWorldPosition = float4(0, 0, 0, 1);
|
|
// Use 'FLATTEN' instead of 'BRANCH' because of nVidia driver compiler bug: see UE-108339 - nVidia is working on a driver side fix right now
|
|
FLATTEN
|
|
if ((GetPrimitiveData(VertexParameters).Flags & PRIMITIVE_SCENE_DATA_FLAG_OUTPUT_VELOCITY) != 0)
|
|
{
|
|
PrevTranslatedWorldPosition = VertexFactoryGetPreviousWorldPosition( Input, VFIntermediates );
|
|
VertexParameters = GetMaterialVertexParameters(Input, VFIntermediates, PrevTranslatedWorldPosition.xyz, TangentToLocal, true);
|
|
PrevTranslatedWorldPosition.xyz += GetMaterialPreviousWorldPositionOffset(VertexParameters);
|
|
ApplyMaterialPreviousFirstPersonTransform(VertexParameters, PrevTranslatedWorldPosition.xyz);
|
|
|
|
PrevTranslatedWorldPosition = mul(float4(PrevTranslatedWorldPosition.xyz, 1), ResolvedView.PrevTranslatedWorldToClip);
|
|
}
|
|
|
|
// compute the old screen pos with the old world position and the old camera matrix
|
|
Output.BasePassInterpolants.VelocityPrevScreenPosition = INVARIANT(PrevTranslatedWorldPosition);
|
|
}
|
|
#endif // WRITES_VELOCITY_TO_GBUFFER
|
|
}
|