Files
UnrealEngine/Engine/Shaders/Private/VelocityShader.usf
2025-05-18 13:04:45 +08:00

186 lines
7.5 KiB
HLSL

// Copyright Epic Games, Inc. All Rights Reserved.
/*=============================================================================
VelocityShader.usf: Calculates velocity vectors.
=============================================================================*/
#include "Common.ush"
#include "/Engine/Generated/Material.ush"
#include "/Engine/Generated/VertexFactory.ush"
#include "VelocityCommon.ush"
// Move all geometry a little bit towards the camera to not get z fighting with existing depth
// buffer of the same meshes rendered with slightly different float computations.
// This is a positive number as our z buffer is inverted for better precision.
// 0.0f as the isolate code should do a good job to prevent this case (can be increased if that is not the case e.g. if the platform ignores the isolate)
static const float GDepthBias = 0.001f;
struct FVelocityInterpsVSToPS
{
#if !TRANSLUCENCY_VELOCITY_FROM_DEPTH
// float4(PrevScreenPos.xyzw)
float4 PackedVelocityC : TEXCOORD7;
#endif
FVertexFactoryInterpolantsVSToPS FactoryInterpolants;
#if USE_WORLD_POSITION_EXCLUDING_SHADER_OFFSETS && !IS_NANITE_PASS
float3 PixelPositionExcludingWPO : TEXCOORD8;
#endif
};
struct FVelocityVSToPS
{
INVARIANT_OUTPUT float4 Position : SV_POSITION;
FVelocityInterpsVSToPS Interps;
FStereoVSOutput StereoOutput;
};
#define FVertexOutput FVelocityVSToPS
#define VertexFactoryGetInterpolants VertexFactoryGetInterpolantsVSToPS
/*=============================================================================
* Vertex Shader
*============================================================================*/
#if VERTEXSHADER
void MainVertexShader(
FVertexFactoryInput Input,
out FVertexOutput Output
#if USE_GLOBAL_CLIP_PLANE
, out float OutGlobalClipPlaneDistance : SV_ClipDistance
#endif
)
{
StereoSetupVF(Input, Output.StereoOutput);
FVertexFactoryIntermediates VFIntermediates = GetVertexFactoryIntermediates(Input);
float4 TranslatedWorldPosition = VertexFactoryGetWorldPosition( Input, VFIntermediates );
#if USE_WORLD_POSITION_EXCLUDING_SHADER_OFFSETS && !IS_NANITE_PASS
Output.Interps.PixelPositionExcludingWPO = TranslatedWorldPosition.xyz;
#endif
half3x3 TangentToLocal = VertexFactoryGetTangentToLocal( Input, VFIntermediates );
FMaterialVertexParameters VertexParameters = GetMaterialVertexParameters(Input, VFIntermediates, TranslatedWorldPosition.xyz, TangentToLocal);
// Isolate instructions used for world position offset on xbox 360,
// 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.
{
TranslatedWorldPosition.xyz += GetMaterialWorldPositionOffset(VertexParameters);
ApplyMaterialFirstPersonTransform(VertexParameters, TranslatedWorldPosition.xyz);
}
Output.Interps.FactoryInterpolants = VertexFactoryGetInterpolants( Input, VFIntermediates, VertexParameters );
float4 PrevTranslatedWorldPosition = VertexFactoryGetPreviousWorldPosition( Input, VFIntermediates );
VertexParameters = GetMaterialVertexParameters(Input, VFIntermediates, PrevTranslatedWorldPosition.xyz, TangentToLocal, true);
PrevTranslatedWorldPosition.xyz += GetMaterialPreviousWorldPositionOffset(VertexParameters);
ApplyMaterialPreviousFirstPersonTransform(VertexParameters, PrevTranslatedWorldPosition.xyz);
{
// compute the old screen pos with the old world position and the old camera matrix
float4 PrevScreenPosObj = mul(float4(PrevTranslatedWorldPosition.xyz, 1), ResolvedView.PrevTranslatedWorldToClip);
Output.Position = INVARIANT(mul(float4(TranslatedWorldPosition.xyz, 1), ResolvedView.TranslatedWorldToClip));
#if USE_GLOBAL_CLIP_PLANE
OutGlobalClipPlaneDistance = dot(ResolvedView.GlobalClippingPlane, float4(TranslatedWorldPosition.xyz, 1));
#endif
#if !TRANSLUCENCY_VELOCITY_FROM_DEPTH
Output.Interps.PackedVelocityC = INVARIANT(PrevScreenPosObj);
#endif
}
// Move all geometry a little bit towards the camera (to not get z fighting with existing zbuffer of the same meshes rendered with slightly different float computations).
Output.Position.z += View.NumSceneColorMSAASamples > 1 ? GDepthBias * Output.Position.w : 0.0;
#if !TRANSLUCENCY_VELOCITY_FROM_DEPTH
Output.Interps.PackedVelocityC.z += View.NumSceneColorMSAASamples > 1 ? GDepthBias * Output.Position.w : 0.0;
#endif
}
#endif // VERTEXSHADER
/*=============================================================================
* Pixel Shader
*============================================================================*/
#ifndef VELOCITY_THIN_TRANSLUCENT_MODE
#define VELOCITY_THIN_TRANSLUCENT_MODE 0
#endif
void MainPixelShader(
in INPUT_POSITION_QUALIFIERS float4 SvPosition : SV_Position,
FVelocityInterpsVSToPS Input,
FStereoPSInput StereoInput
OPTIONAL_IsFrontFace
OPTIONAL_OutDepthConservative
,out ENCODED_VELOCITY_TYPE OutColor : SV_Target0
#if MATERIALBLENDING_MASKED_USING_COVERAGE
, out uint OutCoverage : SV_Coverage
#endif
)
{
StereoSetupPS(StereoInput);
// Manual clipping here (alpha-test, etc)
FMaterialPixelParameters MaterialParameters = GetMaterialPixelParameters(Input.FactoryInterpolants, SvPosition);
FPixelMaterialInputs PixelMaterialInputs;
float4 ScreenPosition = SvPositionToResolvedScreenPosition(SvPosition);
#if USE_WORLD_POSITION_EXCLUDING_SHADER_OFFSETS && !IS_NANITE_PASS
float3 TranslatedWorldPosition = SvPositionToResolvedTranslatedWorld(SvPosition);
CalcMaterialParametersEx(MaterialParameters, PixelMaterialInputs, SvPosition, ScreenPosition, bIsFrontFace, TranslatedWorldPosition, Input.PixelPositionExcludingWPO);
#else
CalcMaterialParameters(MaterialParameters, PixelMaterialInputs, SvPosition, bIsFrontFace);
#endif
#if OUTPUT_PIXEL_DEPTH_OFFSET
ApplyPixelDepthOffsetToMaterialParameters(MaterialParameters, PixelMaterialInputs, OutDepth);
#if APPLE_DEPTH_BIAS_HACK
OutDepth -= APPLE_DEPTH_BIAS_VALUE;
#endif
#endif
#if MATERIALBLENDING_MASKED_USING_COVERAGE
OutCoverage = DiscardMaterialWithPixelCoverage(MaterialParameters, PixelMaterialInputs);
#else
#if SUBSTRATE_ENABLED
const bool bThinTranslucentMaterial = false;
FSubstrateData SubstrateData = PixelMaterialInputs.GetFrontSubstrateData();
FSubstratePixelHeader SubstratePixelHeader = MaterialParameters.GetFrontSubstrateHeader();
float MaterialOpacity = 1.0f;
if (SubstratePixelHeader.ClosureCount > 0)
{
// Update tree (coverage/transmittance/luminace weights)
const FSubstrateIntegrationSettings Settings = InitSubstrateIntegrationSettings();
const float3 V = MaterialParameters.CameraVector;
SubstratePixelHeader.SubstrateUpdateTree(V, Settings);
MaterialOpacity = SubstratePixelHeader.SubstrateTree.Operators[SubstrateData.OperatorIndex].Coverage;
}
#if SUBSTRATE_USE_PREMULTALPHA_OVERRIDE // AlphaComposite - Premultiplied alpha blending
MaterialOpacity = GetMaterialOpacity(PixelMaterialInputs);
#endif
#else
const bool bThinTranslucentMaterial = VELOCITY_THIN_TRANSLUCENT_MODE > 0;
const float MaterialOpacity = GetMaterialOpacity(PixelMaterialInputs);
#endif
GetMaterialClippingVelocity(MaterialParameters, PixelMaterialInputs, bThinTranslucentMaterial, MaterialOpacity);
#endif
#if !TRANSLUCENCY_VELOCITY_FROM_DEPTH
// 3d velocity, includes camera an object motion
float3 Velocity = Calculate3DVelocity(ScreenPosition, Input.PackedVelocityC);
OutColor = EncodeVelocityToTexture(Velocity, (GetPrimitiveData(MaterialParameters).Flags & PRIMITIVE_SCENE_DATA_FLAG_HAS_PIXEL_ANIMATION) != 0);
#else
// We only want velocity generated from camera movement and depth so write zero which is the special clear color value.
OutColor = 0;
#endif
}