UnityGame/Library/PackageCache/com.unity.render-pipelines.universal/Editor/ShaderGraph/Includes/MotionVectorPass.hlsl

181 lines
7.3 KiB
HLSL
Raw Normal View History

2024-10-27 10:53:47 +03:00
#ifndef SG_MOTION_VECTORS_PASS_INCLUDED
#define SG_MOTION_VECTORS_PASS_INCLUDED
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/MotionVectorsCommon.hlsl"
struct MotionVectorPassAttributes
{
float3 previousPositionOS : TEXCOORD4; // Contains previous frame local vertex position (for skinned meshes)
#if defined (_ADD_PRECOMPUTED_VELOCITY)
float3 alembicMotionVectorOS : TEXCOORD5; // Alembic precomputed object space motion vector (offset from last frame's position)
#endif
};
// Note: these will have z == 0.0f in the pixel shader to save on bandwidth
struct MotionVectorPassVaryings
{
float4 positionCSNoJitter;
float4 previousPositionCSNoJitter;
};
struct PackedMotionVectorPassVaryings
{
float3 positionCSNoJitter : CLIP_POSITION_NO_JITTER;
float3 previousPositionCSNoJitter : PREVIOUS_CLIP_POSITION_NO_JITTER;
};
PackedMotionVectorPassVaryings PackMotionVectorVaryings(MotionVectorPassVaryings regularVaryings)
{
PackedMotionVectorPassVaryings packedVaryings;
packedVaryings.positionCSNoJitter = regularVaryings.positionCSNoJitter.xyw;
packedVaryings.previousPositionCSNoJitter = regularVaryings.previousPositionCSNoJitter.xyw;
return packedVaryings;
}
MotionVectorPassVaryings UnpackMotionVectorVaryings(PackedMotionVectorPassVaryings packedVaryings)
{
MotionVectorPassVaryings regularVaryings;
regularVaryings.positionCSNoJitter = float4(packedVaryings.positionCSNoJitter.xy, 0, packedVaryings.positionCSNoJitter.z);
regularVaryings.previousPositionCSNoJitter = float4(packedVaryings.previousPositionCSNoJitter.xy, 0, packedVaryings.previousPositionCSNoJitter.z);
return regularVaryings;
}
float3 GetLastFrameDeformedPosition(Attributes input, MotionVectorPassOutput currentFrameMvData, float3 previousPositionOS)
{
Attributes lastFrameInputAttributes = input;
lastFrameInputAttributes.positionOS = previousPositionOS;
VertexDescriptionInputs lastFrameVertexDescriptionInputs = BuildVertexDescriptionInputs(lastFrameInputAttributes);
#if defined(AUTOMATIC_TIME_BASED_MOTION_VECTORS) && defined(GRAPH_VERTEX_USES_TIME_PARAMETERS_INPUT)
lastFrameVertexDescriptionInputs.TimeParameters = _LastTimeParameters.xyz;
#endif
VertexDescription lastFrameVertexDescription = VertexDescriptionFunction(lastFrameVertexDescriptionInputs
#if defined(HAVE_VFX_MODIFICATION)
, currentFrameMvData.vfxGraphProperties
#endif
);
#if defined(HAVE_VFX_MODIFICATION)
lastFrameInputAttributes.positionOS = lastFrameVertexDescription.Position.xyz;
lastFrameInputAttributes = VFXTransformMeshToPreviousElement(lastFrameInputAttributes, currentFrameMvData.vfxElementAttributes);
previousPositionOS = lastFrameInputAttributes.positionOS;
#else
previousPositionOS = lastFrameVertexDescription.Position.xyz;
#endif
return previousPositionOS;
}
// -------------------------------------
// Vertex
void vert(
Attributes input,
MotionVectorPassAttributes passInput,
out PackedMotionVectorPassVaryings packedMvOutput,
out PackedVaryings packedOutput)
{
Varyings output = (Varyings)0;
MotionVectorPassVaryings mvOutput = (MotionVectorPassVaryings)0;
MotionVectorPassOutput currentFrameMvData = (MotionVectorPassOutput)0;
output = BuildVaryings(input, currentFrameMvData);
packedOutput = PackVaryings(output);
#if defined(HAVE_VFX_MODIFICATION) && !VFX_FEATURE_MOTION_VECTORS
//Motion vector is enabled in SG but not active in VFX
const bool forceNoMotion = true;
#else
const bool forceNoMotion = unity_MotionVectorsParams.y == 0.0;
#endif
if (!forceNoMotion)
{
#if defined(HAVE_VFX_MODIFICATION)
float3 previousPositionOS = currentFrameMvData.vfxParticlePositionOS;
#if defined(VFX_FEATURE_MOTION_VECTORS_VERTS)
const bool applyDeformation = false;
#else
const bool applyDeformation = true;
#endif
#else
const bool hasDeformation = unity_MotionVectorsParams.x == 1; // Mesh has skinned deformation
float3 previousPositionOS = hasDeformation ? passInput.previousPositionOS : input.positionOS;
#if defined(AUTOMATIC_TIME_BASED_MOTION_VECTORS) && defined(GRAPH_VERTEX_USES_TIME_PARAMETERS_INPUT)
const bool applyDeformation = true;
#else
const bool applyDeformation = hasDeformation;
#endif
#endif
#if defined(FEATURES_GRAPH_VERTEX)
if (applyDeformation)
previousPositionOS = GetLastFrameDeformedPosition(input, currentFrameMvData, previousPositionOS);
else
previousPositionOS = currentFrameMvData.positionOS;
#if defined(FEATURES_GRAPH_VERTEX_MOTION_VECTOR_OUTPUT)
previousPositionOS -= currentFrameMvData.motionVector;
#endif
#endif
#if defined(UNITY_DOTS_INSTANCING_ENABLED) && defined(DOTS_DEFORMED)
// Deformed vertices in DOTS are not cumulative with built-in Unity skinning/blend shapes
// Needs to be called after vertex modification has been applied otherwise it will be
// overwritten by Compute Deform node
ApplyPreviousFrameDeformedVertexPosition(input.vertexID, previousPositionOS);
#endif
#if defined (_ADD_PRECOMPUTED_VELOCITY)
previousPositionOS -= passInput.alembicMotionVectorOS;
#endif
mvOutput.positionCSNoJitter = mul(_NonJitteredViewProjMatrix, float4(currentFrameMvData.positionWS, 1.0f));
#if defined(HAVE_VFX_MODIFICATION)
#if defined(VFX_FEATURE_MOTION_VECTORS_VERTS)
#if defined(FEATURES_GRAPH_VERTEX_MOTION_VECTOR_OUTPUT) || defined(_ADD_PRECOMPUTED_VELOCITY)
#error Unexpected fast path rendering VFX motion vector while there are vertex modification afterwards.
#endif
mvOutput.previousPositionCSNoJitter = VFXGetPreviousClipPosition(input, currentFrameMvData.vfxElementAttributes, mvOutput.positionCSNoJitter);
#else
#if VFX_WORLD_SPACE
//previousPositionOS is already in world space
const float3 previousPositionWS = previousPositionOS;
#else
const float3 previousPositionWS = mul(UNITY_PREV_MATRIX_M, float4(previousPositionOS, 1.0f)).xyz;
#endif
mvOutput.previousPositionCSNoJitter = mul(_PrevViewProjMatrix, float4(previousPositionWS, 1.0f));
#endif
#else
mvOutput.previousPositionCSNoJitter = mul(_PrevViewProjMatrix, mul(UNITY_PREV_MATRIX_M, float4(previousPositionOS, 1.0f)));
#endif
}
packedMvOutput = PackMotionVectorVaryings(mvOutput);
}
// -------------------------------------
// Fragment
float4 frag(
// Note: packedMvInput needs to be before packedInput as otherwise we get the following error in the speed tree 8 SG:
// "Non system-generated input signature parameter () cannot appear after a system generated value"
PackedMotionVectorPassVaryings packedMvInput,
PackedVaryings packedInput) : SV_Target
{
Varyings input = UnpackVaryings(packedInput);
MotionVectorPassVaryings mvInput = UnpackMotionVectorVaryings(packedMvInput);
UNITY_SETUP_INSTANCE_ID(input);
SurfaceDescription surfaceDescription = BuildSurfaceDescription(input);
#if defined(_ALPHATEST_ON)
clip(surfaceDescription.Alpha - surfaceDescription.AlphaClipThreshold);
#endif
#if defined(LOD_FADE_CROSSFADE) && USE_UNITY_CROSSFADE
LODFadeCrossFade(input.positionCS);
#endif
return float4(CalcNdcMotionVectorFromCsPositions(mvInput.positionCSNoJitter, mvInput.previousPositionCSNoJitter), 0, 0);
}
#endif