Files
UnrealEngineUWP/Engine/Shaders/Private/GeometryCacheVertexFactory.ush
Arciel Rekman 5e5328ed0f Fix duplicated instance id semantic (UE-150289).
- Duplicating semantics in vertex shader signature is no longer allowed (by DXC). This change moves such parameters from VS signature into the vertex factory input structures, reusing existing parameters where applicable.

#rb Yuriy.ODonnell, Rob.Srinivasiah
#review @Robert.Srinivasiah, @Jason.Nadro, @Yuriy.ODonnell, @Jules.Blok
#jira UE-150289
#preflight 6282a8857b284e82082f905e

[CL 20242895 by Arciel Rekman in ue5-main branch]
2022-05-17 10:45:04 -04:00

516 lines
17 KiB
Plaintext

// Copyright Epic Games, Inc. All Rights Reserved.
/*=============================================================================
GeometryCacheVertexFactory.hlsl: Vertex factory for geometry caches (supports motion blur data)
=============================================================================*/
#include "VertexFactoryCommon.ush"
/*
Meshes vertices can optionally still be packed and will be unpacked using the following formula:
VertextBuffer.Position*MeshExtension+MeshOrigin
*/
float3 MeshOrigin;
float3 MeshExtension;
/* This vertex type is passed in an extra float4 MotionBlurData. This allows specifying motion blur data in a generic way. The previous
frame's object space position is derived from the MotionBlurData and the current unpacked object space position fields in the following way:
(Vertex.MotionBlurData * MotionBlurDataExtension + MotionBlurDataOrigin) + (UnpackePosition * MotionBlurPositionScale)
Using this formula a number of effects can be achieved with a single vertex shader. Some common examples
- Packed previous vertex positions are bound to MotionBlurData
- MotionBlurDataOrigin: Pevious frame's packed origin
- MotionBlurDataExtension: Previous frame's packed scale multiplied with a time factor (to make motion blur fps independent)
- MotionBlurPositionScale: 0
- Explicit float 3 motion vectors are bound
- MotionBlurDataOrigin: 0
- MotionBlurDataExtension: A negative time factor (to make motion blur fps independent and move the velocities back in time)
- MotionBlurPositionScale: 1
- No motion blur data is not available for this frame (an undefined buffer is bound)
- MotionBlurDataOrigin: 0
- MotionBlurDataExtension: 0
- MotionBlurPositionScale: 1
*/
float3 MotionBlurDataOrigin;
float3 MotionBlurDataExtension;
float MotionBlurPositionScale;
struct FVertexFactoryInput
{
float4 Position : ATTRIBUTE0;
// 0..1
HALF3_TYPE TangentX : ATTRIBUTE1;
// 0..1
// TangentZ.w contains sign of tangent basis determinant
HALF4_TYPE TangentZ : ATTRIBUTE2;
// Per vertex color
float4 Color : ATTRIBUTE3;
// Motion blur input
float4 MotionBlurData : ATTRIBUTE4;
#if NUM_MATERIAL_TEXCOORDS_VERTEX
float2 TexCoords0 : ATTRIBUTE5;
#if NUM_MATERIAL_TEXCOORDS_VERTEX > 1
float2 TexCoords1 : ATTRIBUTE6;
#endif
#if NUM_MATERIAL_TEXCOORDS_VERTEX > 2
float2 TexCoords2 : ATTRIBUTE7;
#endif
#if NUM_MATERIAL_TEXCOORDS_VERTEX > 3
float2 TexCoords3 : ATTRIBUTE8;
#endif
#if NUM_MATERIAL_TEXCOORDS_VERTEX > 4
#error Too many texture coordinate sets defined on Geometry cache vertex input. Max: 4.
#endif
#endif
VF_GPUSCENE_DECLARE_INPUT_BLOCK(13)
VF_INSTANCED_STEREO_DECLARE_INPUT_BLOCK()
};
// RHI_RAYTRACING
#if RAYHITGROUPSHADER
FVertexFactoryInput LoadVertexFactoryInputForHGS(uint TriangleIndex, int VertexIndex)
{
FVertexFactoryInput Input;
FTriangleBaseAttributes Tri = LoadTriangleBaseAttributes(TriangleIndex);
uint VertexId = Tri.Indices[VertexIndex];
Input.Position.x = GeomCacheMVF.Position[VertexId * 3 + 0];
Input.Position.y = GeomCacheMVF.Position[VertexId * 3 + 1];
Input.Position.z = GeomCacheMVF.Position[VertexId * 3 + 2];
Input.TangentX = GeomCacheMVF.TangentX[VertexId].xyz;
Input.TangentZ = GeomCacheMVF.TangentZ[VertexId];
Input.Color = GeomCacheMVF.Color[VertexId];
Input.MotionBlurData.x = GeomCacheMVF.MotionBlurData[VertexId * 3 + 0];
Input.MotionBlurData.y = GeomCacheMVF.MotionBlurData[VertexId * 3 + 1];
Input.MotionBlurData.z = GeomCacheMVF.MotionBlurData[VertexId * 3 + 2];
#if NUM_MATERIAL_TEXCOORDS_VERTEX
float2 TexCoordXY = float2(GeomCacheMVF.TexCoords[VertexId * 2 + 0], GeomCacheMVF.TexCoords[VertexId * 2 + 1]);
Input.TexCoords0 = TexCoordXY;
#if NUM_MATERIAL_TEXCOORDS_VERTEX > 1
Input.TexCoords1 = TexCoordXY;
#endif
#if NUM_MATERIAL_TEXCOORDS_VERTEX > 2
Input.TexCoords2 = TexCoordXY;
#endif
#if NUM_MATERIAL_TEXCOORDS_VERTEX > 3
Input.TexCoords3 = TexCoordXY;
#endif
#endif
VF_GPUSCENE_SET_INPUT_FOR_RT(Input, GetInstanceUserData(), 0U);
return Input;
}
#endif
struct FPositionOnlyVertexFactoryInput
{
float4 Position : ATTRIBUTE0;
VF_GPUSCENE_DECLARE_INPUT_BLOCK(1)
VF_INSTANCED_STEREO_DECLARE_INPUT_BLOCK()
};
struct FPositionAndNormalOnlyVertexFactoryInput
{
float4 Position : ATTRIBUTE0;
float4 Normal : ATTRIBUTE1;
VF_GPUSCENE_DECLARE_INPUT_BLOCK(2)
VF_INSTANCED_STEREO_DECLARE_INPUT_BLOCK()
};
/** for depth-only pass */
float4 VertexFactoryGetWorldPosition(FPositionOnlyVertexFactoryInput Input)
{
FSceneDataIntermediates SceneData = VF_GPUSCENE_GET_INTERMEDIATES(Input);
return TransformLocalToTranslatedWorld(Input.Position.xyz, SceneData.InstanceData.LocalToWorld);
}
/** for shadow pass (used for slope bias) */
float4 VertexFactoryGetWorldPosition(FPositionAndNormalOnlyVertexFactoryInput Input)
{
FSceneDataIntermediates SceneData = VF_GPUSCENE_GET_INTERMEDIATES(Input);
return TransformLocalToTranslatedWorld(Input.Position.xyz, SceneData.InstanceData.LocalToWorld);
}
float3 VertexFactoryGetWorldNormal(FPositionAndNormalOnlyVertexFactoryInput Input)
{
FSceneDataIntermediates SceneData = VF_GPUSCENE_GET_INTERMEDIATES(Input);
return RotateLocalToWorld(Input.Normal.xyz, SceneData.InstanceData.LocalToWorld, SceneData.InstanceData.InvNonUniformScale);
}
struct FVertexFactoryInterpolantsVSToPS
{
#if INTERPOLATE_VERTEX_COLOR
float4 Color : COLOR0;
#endif
#if NUM_TEX_COORD_INTERPOLATORS
// Pack interpolators to reduce the number of semantics used
float4 TexCoords[(NUM_TEX_COORD_INTERPOLATORS + 1) / 2] : TEXCOORD0;
#endif
#if INSTANCED_STEREO
nointerpolation uint EyeIndex : PACKED_EYE_INDEX;
#endif
#if VF_USE_PRIMITIVE_SCENE_DATA
nointerpolation uint PrimitiveId : PRIMITIVE_ID;
#endif
TANGENTTOWORLD_INTERPOLATOR_BLOCK
};
#if NUM_TEX_COORD_INTERPOLATORS
float2 GetUV(FVertexFactoryInterpolantsVSToPS Interpolants, int UVIndex)
{
float4 UVVector = Interpolants.TexCoords[UVIndex / 2];
return UVIndex % 2 ? UVVector.zw : UVVector.xy;
}
void SetUV(inout FVertexFactoryInterpolantsVSToPS Interpolants, int UVIndex, float2 InValue)
{
FLATTEN
if (UVIndex % 2)
{
Interpolants.TexCoords[UVIndex / 2].zw = InValue;
}
else
{
Interpolants.TexCoords[UVIndex / 2].xy = InValue;
}
}
#endif
struct FVertexFactoryRayTracingInterpolants
{
FVertexFactoryInterpolantsVSToPS InterpolantsVSToPS;
};
/** Converts from vertex factory specific interpolants to a FMaterialPixelParameters, which is used by material inputs. */
FMaterialPixelParameters GetMaterialPixelParameters(FVertexFactoryInterpolantsVSToPS Interpolants, float4 SvPosition)
{
// GetMaterialPixelParameters is responsible for fully initializing the result
FMaterialPixelParameters Result = MakeInitializedMaterialPixelParameters();
#if NUM_TEX_COORD_INTERPOLATORS
UNROLL
for(int CoordinateIndex = 0;CoordinateIndex < NUM_TEX_COORD_INTERPOLATORS;CoordinateIndex++)
{
Result.TexCoords[CoordinateIndex] = GetUV(Interpolants, CoordinateIndex);
}
#endif
half3 TangentToWorld0 = Interpolants.TangentToWorld0.xyz;
half4 TangentToWorld2 = Interpolants.TangentToWorld2;
Result.TangentToWorld = AssembleTangentToWorld( TangentToWorld0, TangentToWorld2 );
#if USE_WORLDVERTEXNORMAL_CENTER_INTERPOLATION
Result.WorldVertexNormal_Center = Interpolants.TangentToWorld2_Center.xyz;
#endif
Result.UnMirrored = TangentToWorld2.w;
#if INTERPOLATE_VERTEX_COLOR
Result.VertexColor = Interpolants.Color;
#else
Result.VertexColor = 0;
#endif
Result.TwoSidedSign = 1;
#if VF_USE_PRIMITIVE_SCENE_DATA
Result.PrimitiveId = Interpolants.PrimitiveId;
#endif
return Result;
}
#define FBoneMatrix float3x4
// Cache data to avoid multiple calculation
struct FVertexFactoryIntermediates
{
// Unpacked position
float3 UnpackedPosition;
// Tangent Basis
float3x3 TangentToLocal;
float3x3 TangentToWorld;
// Vertex Color
float4 Color;
/** Cached primitive and instance data */
FSceneDataIntermediates SceneData;
};
FPrimitiveSceneData GetPrimitiveData(FVertexFactoryIntermediates Intermediates)
{
return Intermediates.SceneData.Primitive;
}
/** Converts from vertex factory specific input to a FMaterialVertexParameters, which is used by vertex shader material inputs. */
FMaterialVertexParameters GetMaterialVertexParameters(FVertexFactoryInput Input, FVertexFactoryIntermediates Intermediates, float3 WorldPosition, float3x3 TangentToLocal)
{
FMaterialVertexParameters Result = (FMaterialVertexParameters)0;
Result.SceneData = Intermediates.SceneData;
Result.WorldPosition = WorldPosition;
Result.VertexColor = Intermediates.Color;
Result.TangentToWorld = Intermediates.TangentToWorld;
Result.PreSkinnedPosition = Intermediates.UnpackedPosition.xyz;
Result.PreSkinnedNormal = Input.TangentZ.xyz * 2.f - 1.f;
#if NUM_MATERIAL_TEXCOORDS_VERTEX
Result.TexCoords[0] = Input.TexCoords0;
#if NUM_MATERIAL_TEXCOORDS_VERTEX > 1
Result.TexCoords[1] = Input.TexCoords1;
#endif
#if NUM_MATERIAL_TEXCOORDS_VERTEX > 2
Result.TexCoords[2] = Input.TexCoords2;
#endif
#if NUM_MATERIAL_TEXCOORDS_VERTEX > 3
Result.TexCoords[3] = Input.TexCoords3;
#endif
#endif
#if VF_USE_PRIMITIVE_SCENE_DATA
Result.PrimitiveId = Intermediates.SceneData.PrimitiveId;
#endif
return Result;
}
/**
* Unpack position - uncompress xyz position to object space position
*/
float3 UnpackedPosition( FVertexFactoryInput Input )
{
return float3(Input.Position.xyz * GeomCache.MeshExtension + GeomCache.MeshOrigin);
}
/**
* Derive tangent space matrix from vertex interpolants
*/
half3x3 CalcTangentToLocal(FVertexFactoryInput Input)
{
half3x3 Result;
// Unpack to -1 .. 1
half3 TangentX = TangentBias(Input.TangentX);
half4 TangentZ = TangentBias(Input.TangentZ);
// derive the binormal by getting the cross product of the normal and tangent
half3 TangentY = cross(TangentZ.xyz, TangentX) * TangentZ.w;
// Recalculate TangentX off of the other two vectors
// This corrects quantization error since TangentX was passed in as a quantized 8 bit vertex input
// The error shows up most in specular off of a mesh with a smoothed UV seam (normal is smooth, but tangents vary across the seam)
Result[0] = cross(TangentY, TangentZ.xyz) * TangentZ.w;
Result[1] = TangentY;
Result[2] = TangentZ.xyz;
return Result;
}
void CalcTangentToWorld(FVertexFactoryInput Input, FVertexFactoryIntermediates Intermediates, out float3 TangentToWorld0, out float4 TangentToWorld2)
{
float3x3 LocalToWorld = LWCToFloat3x3(Intermediates.SceneData.InstanceData.LocalToWorld);
// Remove scaling.
half3 InvScale = GetPrimitiveData(Intermediates).InvNonUniformScale;
LocalToWorld[0] *= InvScale.x;
LocalToWorld[1] *= InvScale.y;
LocalToWorld[2] *= InvScale.z;
float3x3 TangentToWorld = mul(Intermediates.TangentToLocal, LocalToWorld);
TangentToWorld0 = TangentToWorld[0];
TangentToWorld2 = float4(TangentToWorld[2], Input.TangentZ.w * GetPrimitive_DeterminantSign_FromFlags(GetPrimitiveData(Intermediates).Flags));
}
FVertexFactoryIntermediates GetVertexFactoryIntermediates(FVertexFactoryInput Input)
{
FVertexFactoryIntermediates Intermediates;
Intermediates.SceneData = VF_GPUSCENE_GET_INTERMEDIATES(Input);
Intermediates.UnpackedPosition = UnpackedPosition(Input);
// Fill TangentToLocal
Intermediates.TangentToLocal = CalcTangentToLocal(Input);
float3 TangentToWorld0;
float4 TangentToWorld2;
CalcTangentToWorld(Input, Intermediates, TangentToWorld0, TangentToWorld2);
Intermediates.TangentToWorld = AssembleTangentToWorld(TangentToWorld0, TangentToWorld2);
// Swizzle vertex color.
Intermediates.Color = Input.Color FCOLOR_COMPONENT_SWIZZLE;
return Intermediates;
}
float3 VertexFactoryGetWorldNormal(FVertexFactoryInput Input, FVertexFactoryIntermediates Intermediates)
{
return Intermediates.TangentToWorld[2];
}
/**
* Get the 3x3 tangent basis vectors for this vertex factory
*
* @param Input - vertex input stream structure
* @return 3x3 matrix
*/
float3x3 VertexFactoryGetTangentToLocal( FVertexFactoryInput Input, FVertexFactoryIntermediates Intermediates)
{
return Intermediates.TangentToLocal;
}
float4 VertexFactoryGetWorldPosition(FVertexFactoryInput Input, FVertexFactoryIntermediates Intermediates)
{
return TransformLocalToTranslatedWorld(Intermediates.UnpackedPosition, Intermediates.SceneData.InstanceData.LocalToWorld);
}
float4 VertexFactoryGetRasterizedWorldPosition(FVertexFactoryInput Input, FVertexFactoryIntermediates Intermediates, float4 InWorldPosition)
{
return InWorldPosition;
}
float3 VertexFactoryGetPositionForVertexLighting(FVertexFactoryInput Input, FVertexFactoryIntermediates Intermediates, float3 TranslatedWorldPosition)
{
return TranslatedWorldPosition;
}
FVertexFactoryInterpolantsVSToPS VertexFactoryGetInterpolantsVSToPS(FVertexFactoryInput Input, FVertexFactoryIntermediates Intermediates, FMaterialVertexParameters VertexParameters)
{
FVertexFactoryInterpolantsVSToPS Interpolants;
// Initialize the whole struct to 0
Interpolants = (FVertexFactoryInterpolantsVSToPS)0;
#if NUM_TEX_COORD_INTERPOLATORS
float2 CustomizedUVs[NUM_TEX_COORD_INTERPOLATORS];
GetMaterialCustomizedUVs(VertexParameters, CustomizedUVs);
GetCustomInterpolators(VertexParameters, CustomizedUVs);
UNROLL
for (int CoordinateIndex = 0; CoordinateIndex < NUM_TEX_COORD_INTERPOLATORS; CoordinateIndex++)
{
SetUV(Interpolants, CoordinateIndex, CustomizedUVs[CoordinateIndex]);
}
#endif
//Packs the TangentToWorld matrix into the interpolants.
Interpolants.TangentToWorld0.w = 0;
CalcTangentToWorld(Input, Intermediates, Interpolants.TangentToWorld0.xyz, Interpolants.TangentToWorld2);
#if USE_WORLDVERTEXNORMAL_CENTER_INTERPOLATION
Interpolants.TangentToWorld2_Center = Interpolants.TangentToWorld2;
#endif
#if INTERPOLATE_VERTEX_COLOR
Interpolants.Color = Intermediates.Color;
#endif
#if INSTANCED_STEREO
Interpolants.EyeIndex = 0;
#endif
#if VF_USE_PRIMITIVE_SCENE_DATA
Interpolants.PrimitiveId = Intermediates.SceneData.PrimitiveId;
#endif
return Interpolants;
}
// @return The previous position of the vertex in object space.
float3 CalcPreviousPosition(FVertexFactoryInput Input, FVertexFactoryIntermediates Intermediates)
{
float3 PreviousPosition = (Input.MotionBlurData.xyz * GeomCache.MotionBlurDataExtension + GeomCache.MotionBlurDataOrigin) + Intermediates.UnpackedPosition * GeomCache.MotionBlurPositionScale;
#if 0
float ExaggerateMotion = 10.0;
float3 Delta = Intermediates.UnpackedPosition - PreviousPosition;
PreviousPosition = Intermediates.UnpackedPosition - Delta * ExaggerateMotion;
#endif
return PreviousPosition;
}
// @return previous translated world position
float4 VertexFactoryGetPreviousWorldPosition(FVertexFactoryInput Input, FVertexFactoryIntermediates Intermediates)
{
float4x4 PreviousLocalToWorldTranslated = LWCMultiplyTranslation(GetPrimitiveData(Intermediates).PreviousLocalToWorld, ResolvedView.PrevPreViewTranslation);
float4 PrevSkinPosInWorld = mul(float4(CalcPreviousPosition(Input, Intermediates),1), PreviousLocalToWorldTranslated);
return PrevSkinPosInWorld;
}
#if NEEDS_VERTEX_FACTORY_INTERPOLATION
float2 VertexFactoryGetRayTracingTextureCoordinate( FVertexFactoryRayTracingInterpolants Interpolants )
{
#if NUM_MATERIAL_TEXCOORDS
return Interpolants.InterpolantsVSToPS.TexCoords[0].xy;
#else // #if NUM_MATERIAL_TEXCOORDS
return float2(0,0);
#endif // #if NUM_MATERIAL_TEXCOORDS
}
FVertexFactoryInterpolantsVSToPS VertexFactoryAssignInterpolants(FVertexFactoryRayTracingInterpolants Input)
{
return Input.InterpolantsVSToPS;
}
FVertexFactoryRayTracingInterpolants VertexFactoryGetRayTracingInterpolants(FVertexFactoryInput Input, FVertexFactoryIntermediates Intermediates, FMaterialVertexParameters VertexParameters)
{
FVertexFactoryRayTracingInterpolants Interpolants;
Interpolants.InterpolantsVSToPS = VertexFactoryGetInterpolantsVSToPS(Input, Intermediates, VertexParameters);
return Interpolants;
}
FVertexFactoryRayTracingInterpolants VertexFactoryInterpolate(FVertexFactoryRayTracingInterpolants a, float aInterp, FVertexFactoryRayTracingInterpolants b, float bInterp)
{
FVertexFactoryRayTracingInterpolants O;
INTERPOLATE_MEMBER(InterpolantsVSToPS.TangentToWorld0.xyz);
INTERPOLATE_MEMBER(InterpolantsVSToPS.TangentToWorld2);
#if INTERPOLATE_VERTEX_COLOR
INTERPOLATE_MEMBER(InterpolantsVSToPS.Color);
#endif
#if NUM_TEX_COORD_INTERPOLATORS
UNROLL
for(int tc = 0; tc < (NUM_TEX_COORD_INTERPOLATORS + 1) / 2; ++tc)
{
INTERPOLATE_MEMBER(InterpolantsVSToPS.TexCoords[tc]);
}
#endif
#if VF_USE_PRIMITIVE_SCENE_DATA
O.InterpolantsVSToPS.PrimitiveId = a.InterpolantsVSToPS.PrimitiveId;
#endif
return O;
}
#endif // #if NEEDS_VERTEX_FACTORY_INTERPOLATION
float4 VertexFactoryGetTranslatedPrimitiveVolumeBounds(FVertexFactoryInterpolantsVSToPS Interpolants)
{
return 0;
}
uint VertexFactoryGetPrimitiveId(FVertexFactoryInterpolantsVSToPS Interpolants)
{
#if VF_USE_PRIMITIVE_SCENE_DATA
return Interpolants.PrimitiveId;
#else // VF_USE_PRIMITIVE_SCENE_DATA
return 0;
#endif // VF_USE_PRIMITIVE_SCENE_DATA
}
#include "VertexFactoryDefaultInterface.ush"