2019-12-27 09:26:59 -05:00
|
|
|
// Copyright Epic Games, Inc. All Rights Reserved.
|
2018-04-12 16:57:51 -04:00
|
|
|
|
|
|
|
|
/*=============================================================================
|
|
|
|
|
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:
|
2018-12-14 11:54:34 -05:00
|
|
|
VertextBuffer.Position*MeshExtension+MeshOrigin
|
2018-04-12 16:57:51 -04:00
|
|
|
*/
|
2018-12-14 11:54:34 -05:00
|
|
|
float3 MeshOrigin;
|
|
|
|
|
float3 MeshExtension;
|
2018-04-12 16:57:51 -04:00
|
|
|
|
|
|
|
|
/* 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:
|
|
|
|
|
|
2018-12-14 11:54:34 -05:00
|
|
|
(Vertex.MotionBlurData * MotionBlurDataExtension + MotionBlurDataOrigin) + (UnpackePosition * MotionBlurPositionScale)
|
2018-04-12 16:57:51 -04:00
|
|
|
|
|
|
|
|
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
|
|
|
|
|
*/
|
2018-12-14 11:54:34 -05:00
|
|
|
float3 MotionBlurDataOrigin;
|
|
|
|
|
float3 MotionBlurDataExtension;
|
2018-04-12 16:57:51 -04:00
|
|
|
float MotionBlurPositionScale;
|
|
|
|
|
|
|
|
|
|
struct FVertexFactoryInput
|
|
|
|
|
{
|
|
|
|
|
float4 Position : ATTRIBUTE0;
|
|
|
|
|
// 0..1
|
2021-02-16 08:45:04 -04:00
|
|
|
HALF3_TYPE TangentX : ATTRIBUTE1;
|
2018-04-12 16:57:51 -04:00
|
|
|
// 0..1
|
|
|
|
|
// TangentZ.w contains sign of tangent basis determinant
|
2021-02-16 08:45:04 -04:00
|
|
|
HALF4_TYPE TangentZ : ATTRIBUTE2;
|
2018-04-12 16:57:51 -04:00
|
|
|
|
|
|
|
|
// Per vertex color
|
|
|
|
|
float4 Color : ATTRIBUTE3;
|
|
|
|
|
|
|
|
|
|
// Motion blur input
|
|
|
|
|
float4 MotionBlurData : ATTRIBUTE4;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if NUM_MATERIAL_TEXCOORDS_VERTEX
|
2021-08-11 07:10:27 -04:00
|
|
|
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
|
2023-05-10 04:02:18 -04:00
|
|
|
|
|
|
|
|
#if NUM_MATERIAL_TEXCOORDS_VERTEX > 4
|
|
|
|
|
#error Too many texture coordinate sets defined on Geometry cache vertex input. Max: 4.
|
|
|
|
|
#endif
|
2018-04-12 16:57:51 -04:00
|
|
|
#endif
|
2021-09-01 07:12:02 -04:00
|
|
|
|
|
|
|
|
VF_GPUSCENE_DECLARE_INPUT_BLOCK(13)
|
2022-05-17 10:45:04 -04:00
|
|
|
VF_INSTANCED_STEREO_DECLARE_INPUT_BLOCK()
|
2018-04-12 16:57:51 -04:00
|
|
|
};
|
|
|
|
|
|
2019-01-22 12:03:56 -05:00
|
|
|
// RHI_RAYTRACING
|
|
|
|
|
#if RAYHITGROUPSHADER
|
2019-10-01 13:03:04 -04:00
|
|
|
FVertexFactoryInput LoadVertexFactoryInputForHGS(uint TriangleIndex, int VertexIndex)
|
2019-01-22 12:03:56 -05:00
|
|
|
{
|
|
|
|
|
FVertexFactoryInput Input;
|
|
|
|
|
|
2019-10-11 15:33:31 -04:00
|
|
|
FTriangleBaseAttributes Tri = LoadTriangleBaseAttributes(TriangleIndex);
|
|
|
|
|
uint VertexId = Tri.Indices[VertexIndex];
|
2019-01-22 12:03:56 -05:00
|
|
|
|
|
|
|
|
Input.Position.x = GeomCacheMVF.Position[VertexId * 3 + 0];
|
|
|
|
|
Input.Position.y = GeomCacheMVF.Position[VertexId * 3 + 1];
|
|
|
|
|
Input.Position.z = GeomCacheMVF.Position[VertexId * 3 + 2];
|
2019-09-14 09:45:25 -04:00
|
|
|
Input.TangentX = GeomCacheMVF.TangentX[VertexId].xyz;
|
2019-01-22 12:03:56 -05:00
|
|
|
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
|
2021-08-11 13:19:13 -04:00
|
|
|
float2 TexCoordXY = float2(GeomCacheMVF.TexCoords[VertexId * 2 + 0], GeomCacheMVF.TexCoords[VertexId * 2 + 1]);
|
2021-06-10 13:13:24 -04:00
|
|
|
|
2021-08-11 13:19:13 -04:00
|
|
|
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
|
2019-01-22 12:03:56 -05:00
|
|
|
#endif
|
|
|
|
|
|
2021-09-01 07:12:02 -04:00
|
|
|
VF_GPUSCENE_SET_INPUT_FOR_RT(Input, GetInstanceUserData(), 0U);
|
|
|
|
|
|
2019-01-22 12:03:56 -05:00
|
|
|
return Input;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2018-04-12 16:57:51 -04:00
|
|
|
|
|
|
|
|
struct FPositionOnlyVertexFactoryInput
|
|
|
|
|
{
|
|
|
|
|
float4 Position : ATTRIBUTE0;
|
2021-09-01 07:12:02 -04:00
|
|
|
VF_GPUSCENE_DECLARE_INPUT_BLOCK(1)
|
2022-05-17 10:45:04 -04:00
|
|
|
VF_INSTANCED_STEREO_DECLARE_INPUT_BLOCK()
|
2018-04-12 16:57:51 -04:00
|
|
|
};
|
|
|
|
|
|
2019-06-11 18:27:07 -04:00
|
|
|
struct FPositionAndNormalOnlyVertexFactoryInput
|
|
|
|
|
{
|
|
|
|
|
float4 Position : ATTRIBUTE0;
|
|
|
|
|
float4 Normal : ATTRIBUTE1;
|
2021-09-01 07:12:02 -04:00
|
|
|
VF_GPUSCENE_DECLARE_INPUT_BLOCK(2)
|
2022-05-17 10:45:04 -04:00
|
|
|
VF_INSTANCED_STEREO_DECLARE_INPUT_BLOCK()
|
2019-06-11 18:27:07 -04:00
|
|
|
};
|
|
|
|
|
|
2018-04-12 16:57:51 -04:00
|
|
|
/** for depth-only pass */
|
|
|
|
|
float4 VertexFactoryGetWorldPosition(FPositionOnlyVertexFactoryInput Input)
|
|
|
|
|
{
|
2021-09-01 07:12:02 -04:00
|
|
|
FSceneDataIntermediates SceneData = VF_GPUSCENE_GET_INTERMEDIATES(Input);
|
|
|
|
|
return TransformLocalToTranslatedWorld(Input.Position.xyz, SceneData.InstanceData.LocalToWorld);
|
2019-06-11 18:27:07 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** for shadow pass (used for slope bias) */
|
|
|
|
|
float4 VertexFactoryGetWorldPosition(FPositionAndNormalOnlyVertexFactoryInput Input)
|
|
|
|
|
{
|
2021-09-01 07:12:02 -04:00
|
|
|
FSceneDataIntermediates SceneData = VF_GPUSCENE_GET_INTERMEDIATES(Input);
|
|
|
|
|
return TransformLocalToTranslatedWorld(Input.Position.xyz, SceneData.InstanceData.LocalToWorld);
|
2019-06-11 18:27:07 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float3 VertexFactoryGetWorldNormal(FPositionAndNormalOnlyVertexFactoryInput Input)
|
|
|
|
|
{
|
2021-09-01 07:12:02 -04:00
|
|
|
FSceneDataIntermediates SceneData = VF_GPUSCENE_GET_INTERMEDIATES(Input);
|
|
|
|
|
return RotateLocalToWorld(Input.Normal.xyz, SceneData.InstanceData.LocalToWorld, SceneData.InstanceData.InvNonUniformScale);
|
2018-04-12 16:57:51 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct FVertexFactoryInterpolantsVSToPS
|
|
|
|
|
{
|
2019-01-22 12:03:56 -05:00
|
|
|
#if INTERPOLATE_VERTEX_COLOR
|
2018-04-12 16:57:51 -04:00
|
|
|
float4 Color : COLOR0;
|
2019-01-22 12:03:56 -05:00
|
|
|
#endif
|
2018-04-12 16:57:51 -04:00
|
|
|
|
|
|
|
|
#if NUM_TEX_COORD_INTERPOLATORS
|
2021-07-15 10:11:35 -04:00
|
|
|
// Pack interpolators to reduce the number of semantics used
|
|
|
|
|
float4 TexCoords[(NUM_TEX_COORD_INTERPOLATORS + 1) / 2] : TEXCOORD0;
|
2018-04-12 16:57:51 -04:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if INSTANCED_STEREO
|
2019-01-17 05:02:52 -05:00
|
|
|
nointerpolation uint EyeIndex : PACKED_EYE_INDEX;
|
2018-04-12 16:57:51 -04:00
|
|
|
#endif
|
2019-01-22 12:03:56 -05:00
|
|
|
|
2021-09-01 07:12:02 -04:00
|
|
|
#if VF_USE_PRIMITIVE_SCENE_DATA
|
|
|
|
|
nointerpolation uint PrimitiveId : PRIMITIVE_ID;
|
|
|
|
|
#endif
|
|
|
|
|
|
2019-01-22 12:03:56 -05:00
|
|
|
TANGENTTOWORLD_INTERPOLATOR_BLOCK
|
2018-04-12 16:57:51 -04:00
|
|
|
};
|
|
|
|
|
|
2021-07-15 10:11:35 -04:00
|
|
|
#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
|
|
|
|
|
|
2021-04-14 15:26:31 -04:00
|
|
|
struct FVertexFactoryRayTracingInterpolants
|
2018-04-12 16:57:51 -04:00
|
|
|
{
|
|
|
|
|
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++)
|
|
|
|
|
{
|
2021-07-15 10:11:35 -04:00
|
|
|
Result.TexCoords[CoordinateIndex] = GetUV(Interpolants, CoordinateIndex);
|
2018-04-12 16:57:51 -04:00
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
half3 TangentToWorld0 = Interpolants.TangentToWorld0.xyz;
|
|
|
|
|
half4 TangentToWorld2 = Interpolants.TangentToWorld2;
|
|
|
|
|
Result.TangentToWorld = AssembleTangentToWorld( TangentToWorld0, TangentToWorld2 );
|
2019-01-22 12:03:56 -05:00
|
|
|
#if USE_WORLDVERTEXNORMAL_CENTER_INTERPOLATION
|
|
|
|
|
Result.WorldVertexNormal_Center = Interpolants.TangentToWorld2_Center.xyz;
|
|
|
|
|
#endif
|
|
|
|
|
Result.UnMirrored = TangentToWorld2.w;
|
|
|
|
|
#if INTERPOLATE_VERTEX_COLOR
|
2018-04-12 16:57:51 -04:00
|
|
|
Result.VertexColor = Interpolants.Color;
|
2019-01-22 12:03:56 -05:00
|
|
|
#else
|
|
|
|
|
Result.VertexColor = 0;
|
|
|
|
|
#endif
|
2018-04-12 16:57:51 -04:00
|
|
|
Result.TwoSidedSign = 1;
|
2021-09-01 07:12:02 -04:00
|
|
|
|
|
|
|
|
#if VF_USE_PRIMITIVE_SCENE_DATA
|
|
|
|
|
Result.PrimitiveId = Interpolants.PrimitiveId;
|
|
|
|
|
#endif
|
|
|
|
|
|
2018-04-12 16:57:51 -04:00
|
|
|
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;
|
2021-08-07 07:16:17 -04:00
|
|
|
/** Cached primitive and instance data */
|
|
|
|
|
FSceneDataIntermediates SceneData;
|
2018-04-12 16:57:51 -04:00
|
|
|
};
|
|
|
|
|
|
2021-08-07 07:16:17 -04:00
|
|
|
FPrimitiveSceneData GetPrimitiveData(FVertexFactoryIntermediates Intermediates)
|
|
|
|
|
{
|
|
|
|
|
return Intermediates.SceneData.Primitive;
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-12 16:57:51 -04:00
|
|
|
/** 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)
|
|
|
|
|
{
|
2023-03-09 17:51:49 -05:00
|
|
|
FMaterialVertexParameters Result = MakeInitializedMaterialVertexParameters();
|
2021-08-07 07:16:17 -04:00
|
|
|
Result.SceneData = Intermediates.SceneData;
|
2018-04-12 16:57:51 -04:00
|
|
|
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
|
2021-08-11 07:10:27 -04:00
|
|
|
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
|
2018-04-12 16:57:51 -04:00
|
|
|
#endif
|
2021-09-01 07:12:02 -04:00
|
|
|
|
|
|
|
|
#if VF_USE_PRIMITIVE_SCENE_DATA
|
|
|
|
|
Result.PrimitiveId = Intermediates.SceneData.PrimitiveId;
|
|
|
|
|
#endif
|
|
|
|
|
|
2018-04-12 16:57:51 -04:00
|
|
|
return Result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Unpack position - uncompress xyz position to object space position
|
|
|
|
|
*/
|
|
|
|
|
float3 UnpackedPosition( FVertexFactoryInput Input )
|
|
|
|
|
{
|
2021-09-01 07:12:02 -04:00
|
|
|
return float3(Input.Position.xyz * GeomCache.MeshExtension + GeomCache.MeshOrigin);
|
2018-04-12 16:57:51 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 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;
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-22 12:03:56 -05:00
|
|
|
void CalcTangentToWorld(FVertexFactoryInput Input, FVertexFactoryIntermediates Intermediates, out float3 TangentToWorld0, out float4 TangentToWorld2)
|
2018-04-12 16:57:51 -04:00
|
|
|
{
|
Merging Dev-LWCRendering into Main, this includes initial work to support rendering with LWC-scale position
Basic approach is to add HLSL types FLWCScalar, FLWCMatrix, FLWCVector, etc. Inside shaders, absolute world space position values should be represented as FLWCVector3. Matrices that transform *into* absolute world space become FLWCMatrix. Matrices that transform *from* world space become FLWCInverseMatrix. Generally LWC values work by extending the regular 'float' value with an additional tile coordinate. Final tile size will be a trade-off between scale/accuracy; I'm using 256k for now, but may need to be adjusted. Value represented by a FLWCVector thus becomes V.Tile * TileSize + V.Offset. Most operations can be performed directly on LWC values. There are HLSL functions like LWCAdd, LWCSub, LWCMultiply, LWCDivide (operator overloading would be really nice here). The goal is to stay with LWC values for as long as needed, then convert to regular float values when possible. One thing that comes up a lot is working in translated (rather than absolute) world space. WorldSpace + View.PrevPreViewTranslation = TranslatedWorldspace. Except 'View.PrevPreViewTranslation' is now a FLWCVector3, and WorldSpace quantities should be as well. So that becomes LWCAdd(WorldSpace, View.PrevPreViewTranslation) = TranslatedWorldspace. Assuming that we're talking about a position that's "reasonably close" to the camera, it should be safe to convert the translated WS value to float. The 'tile' coordinate of the 2 LWC values should cancel out when added together in this case. I've done some work throughout the shader code to do this. Materials are fully supporting LWC-values as well. Projective texturing and vertex animation materials that I've tested work correctly even when positioned "far away" from the origin.
Lots of work remains to fully convert all of our shader code. There's a function LWCHackToFloat(), which is a simple wrapper for LWCToFloat(). The idea of HackToFloat is to mark places that need further attention, where I'm simply converting absolute WS positions to float, to get shaders to compile. Shaders converted in this way should continue to work for all existing content (without LWC-scale values), but they will break if positions get too large.
General overview of changed files:
LargeWorldCoordinates.ush - This defines the FLWC types and operations
GPUScene.cpp, SceneData.ush - Primitives add an extra 'float3' tile coordinate. Instance data is unchanged, so instances need to stay within single-precision range of the primitive origin. Could potentially split instances behind the scenes (I think) if we don't want this limitation
HLSLMaterialDerivativeAutogen.cpp, HLSLMaterialTranslator.cpp, Preshader.cpp - Translated materials to use LWC values
SceneView.cpp, SceneRelativeViewMatrices.cpp, ShaderCompiler.cpp, InstancedStereo.ush - View uniform buffer includes LWC values where appropriate
#jira UE-117101
#rb arne.schober, Michael.Galetzka
[CL 17787435 by Ben Ingram in ue5-main branch]
2021-10-12 13:29:45 -04:00
|
|
|
float3x3 LocalToWorld = LWCToFloat3x3(Intermediates.SceneData.InstanceData.LocalToWorld);
|
2018-04-12 16:57:51 -04:00
|
|
|
|
|
|
|
|
// Remove scaling.
|
2021-08-07 07:16:17 -04:00
|
|
|
half3 InvScale = GetPrimitiveData(Intermediates).InvNonUniformScale;
|
2018-04-12 16:57:51 -04:00
|
|
|
LocalToWorld[0] *= InvScale.x;
|
|
|
|
|
LocalToWorld[1] *= InvScale.y;
|
|
|
|
|
LocalToWorld[2] *= InvScale.z;
|
|
|
|
|
|
2019-01-22 12:03:56 -05:00
|
|
|
float3x3 TangentToWorld = mul(Intermediates.TangentToLocal, LocalToWorld);
|
|
|
|
|
|
|
|
|
|
TangentToWorld0 = TangentToWorld[0];
|
2021-08-07 07:16:17 -04:00
|
|
|
TangentToWorld2 = float4(TangentToWorld[2], Input.TangentZ.w * GetPrimitive_DeterminantSign_FromFlags(GetPrimitiveData(Intermediates).Flags));
|
2018-04-12 16:57:51 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FVertexFactoryIntermediates GetVertexFactoryIntermediates(FVertexFactoryInput Input)
|
|
|
|
|
{
|
|
|
|
|
FVertexFactoryIntermediates Intermediates;
|
2021-08-07 07:16:17 -04:00
|
|
|
Intermediates.SceneData = VF_GPUSCENE_GET_INTERMEDIATES(Input);
|
2018-04-12 16:57:51 -04:00
|
|
|
Intermediates.UnpackedPosition = UnpackedPosition(Input);
|
|
|
|
|
|
|
|
|
|
// Fill TangentToLocal
|
|
|
|
|
Intermediates.TangentToLocal = CalcTangentToLocal(Input);
|
2019-06-11 18:27:07 -04:00
|
|
|
|
|
|
|
|
float3 TangentToWorld0;
|
|
|
|
|
float4 TangentToWorld2;
|
|
|
|
|
CalcTangentToWorld(Input, Intermediates, TangentToWorld0, TangentToWorld2);
|
|
|
|
|
Intermediates.TangentToWorld = AssembleTangentToWorld(TangentToWorld0, TangentToWorld2);
|
2018-04-12 16:57:51 -04:00
|
|
|
|
|
|
|
|
// Swizzle vertex color.
|
|
|
|
|
Intermediates.Color = Input.Color FCOLOR_COMPONENT_SWIZZLE;
|
|
|
|
|
|
|
|
|
|
return Intermediates;
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-11 18:27:07 -04:00
|
|
|
float3 VertexFactoryGetWorldNormal(FVertexFactoryInput Input, FVertexFactoryIntermediates Intermediates)
|
|
|
|
|
{
|
|
|
|
|
return Intermediates.TangentToWorld[2];
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-12 16:57:51 -04:00
|
|
|
/**
|
|
|
|
|
* 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)
|
|
|
|
|
{
|
2021-09-01 07:12:02 -04:00
|
|
|
return TransformLocalToTranslatedWorld(Intermediates.UnpackedPosition, Intermediates.SceneData.InstanceData.LocalToWorld);
|
2018-04-12 16:57:51 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
2021-07-15 10:11:35 -04:00
|
|
|
// Initialize the whole struct to 0
|
|
|
|
|
Interpolants = (FVertexFactoryInterpolantsVSToPS)0;
|
|
|
|
|
|
2018-04-12 16:57:51 -04:00
|
|
|
#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++)
|
|
|
|
|
{
|
2021-07-15 10:11:35 -04:00
|
|
|
SetUV(Interpolants, CoordinateIndex, CustomizedUVs[CoordinateIndex]);
|
2018-04-12 16:57:51 -04:00
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
//Packs the TangentToWorld matrix into the interpolants.
|
2019-01-22 12:03:56 -05:00
|
|
|
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
|
2018-04-12 16:57:51 -04:00
|
|
|
Interpolants.Color = Intermediates.Color;
|
2019-01-22 12:03:56 -05:00
|
|
|
#endif
|
2018-04-12 16:57:51 -04:00
|
|
|
|
|
|
|
|
#if INSTANCED_STEREO
|
2019-01-17 05:02:52 -05:00
|
|
|
Interpolants.EyeIndex = 0;
|
2018-04-12 16:57:51 -04:00
|
|
|
#endif
|
|
|
|
|
|
2021-09-01 07:12:02 -04:00
|
|
|
#if VF_USE_PRIMITIVE_SCENE_DATA
|
|
|
|
|
Interpolants.PrimitiveId = Intermediates.SceneData.PrimitiveId;
|
|
|
|
|
#endif
|
|
|
|
|
|
2018-04-12 16:57:51 -04:00
|
|
|
return Interpolants;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// @return The previous position of the vertex in object space.
|
|
|
|
|
float3 CalcPreviousPosition(FVertexFactoryInput Input, FVertexFactoryIntermediates Intermediates)
|
|
|
|
|
{
|
2019-01-22 12:03:56 -05:00
|
|
|
float3 PreviousPosition = (Input.MotionBlurData.xyz * GeomCache.MotionBlurDataExtension + GeomCache.MotionBlurDataOrigin) + Intermediates.UnpackedPosition * GeomCache.MotionBlurPositionScale;
|
2018-04-12 16:57:51 -04:00
|
|
|
#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)
|
|
|
|
|
{
|
Merging Dev-LWCRendering into Main, this includes initial work to support rendering with LWC-scale position
Basic approach is to add HLSL types FLWCScalar, FLWCMatrix, FLWCVector, etc. Inside shaders, absolute world space position values should be represented as FLWCVector3. Matrices that transform *into* absolute world space become FLWCMatrix. Matrices that transform *from* world space become FLWCInverseMatrix. Generally LWC values work by extending the regular 'float' value with an additional tile coordinate. Final tile size will be a trade-off between scale/accuracy; I'm using 256k for now, but may need to be adjusted. Value represented by a FLWCVector thus becomes V.Tile * TileSize + V.Offset. Most operations can be performed directly on LWC values. There are HLSL functions like LWCAdd, LWCSub, LWCMultiply, LWCDivide (operator overloading would be really nice here). The goal is to stay with LWC values for as long as needed, then convert to regular float values when possible. One thing that comes up a lot is working in translated (rather than absolute) world space. WorldSpace + View.PrevPreViewTranslation = TranslatedWorldspace. Except 'View.PrevPreViewTranslation' is now a FLWCVector3, and WorldSpace quantities should be as well. So that becomes LWCAdd(WorldSpace, View.PrevPreViewTranslation) = TranslatedWorldspace. Assuming that we're talking about a position that's "reasonably close" to the camera, it should be safe to convert the translated WS value to float. The 'tile' coordinate of the 2 LWC values should cancel out when added together in this case. I've done some work throughout the shader code to do this. Materials are fully supporting LWC-values as well. Projective texturing and vertex animation materials that I've tested work correctly even when positioned "far away" from the origin.
Lots of work remains to fully convert all of our shader code. There's a function LWCHackToFloat(), which is a simple wrapper for LWCToFloat(). The idea of HackToFloat is to mark places that need further attention, where I'm simply converting absolute WS positions to float, to get shaders to compile. Shaders converted in this way should continue to work for all existing content (without LWC-scale values), but they will break if positions get too large.
General overview of changed files:
LargeWorldCoordinates.ush - This defines the FLWC types and operations
GPUScene.cpp, SceneData.ush - Primitives add an extra 'float3' tile coordinate. Instance data is unchanged, so instances need to stay within single-precision range of the primitive origin. Could potentially split instances behind the scenes (I think) if we don't want this limitation
HLSLMaterialDerivativeAutogen.cpp, HLSLMaterialTranslator.cpp, Preshader.cpp - Translated materials to use LWC values
SceneView.cpp, SceneRelativeViewMatrices.cpp, ShaderCompiler.cpp, InstancedStereo.ush - View uniform buffer includes LWC values where appropriate
#jira UE-117101
#rb arne.schober, Michael.Galetzka
[CL 17787435 by Ben Ingram in ue5-main branch]
2021-10-12 13:29:45 -04:00
|
|
|
float4x4 PreviousLocalToWorldTranslated = LWCMultiplyTranslation(GetPrimitiveData(Intermediates).PreviousLocalToWorld, ResolvedView.PrevPreViewTranslation);
|
2018-04-12 16:57:51 -04:00
|
|
|
|
|
|
|
|
float4 PrevSkinPosInWorld = mul(float4(CalcPreviousPosition(Input, Intermediates),1), PreviousLocalToWorldTranslated);
|
|
|
|
|
return PrevSkinPosInWorld;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-04-14 15:26:31 -04:00
|
|
|
#if NEEDS_VERTEX_FACTORY_INTERPOLATION
|
2021-04-15 13:04:25 -04:00
|
|
|
float2 VertexFactoryGetRayTracingTextureCoordinate( FVertexFactoryRayTracingInterpolants Interpolants )
|
2018-04-12 16:57:51 -04:00
|
|
|
{
|
|
|
|
|
#if NUM_MATERIAL_TEXCOORDS
|
|
|
|
|
return Interpolants.InterpolantsVSToPS.TexCoords[0].xy;
|
|
|
|
|
#else // #if NUM_MATERIAL_TEXCOORDS
|
|
|
|
|
return float2(0,0);
|
|
|
|
|
#endif // #if NUM_MATERIAL_TEXCOORDS
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-14 15:26:31 -04:00
|
|
|
FVertexFactoryInterpolantsVSToPS VertexFactoryAssignInterpolants(FVertexFactoryRayTracingInterpolants Input)
|
2018-04-12 16:57:51 -04:00
|
|
|
{
|
|
|
|
|
return Input.InterpolantsVSToPS;
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-15 13:04:25 -04:00
|
|
|
FVertexFactoryRayTracingInterpolants VertexFactoryGetRayTracingInterpolants(FVertexFactoryInput Input, FVertexFactoryIntermediates Intermediates, FMaterialVertexParameters VertexParameters)
|
2018-04-12 16:57:51 -04:00
|
|
|
{
|
2021-04-14 15:26:31 -04:00
|
|
|
FVertexFactoryRayTracingInterpolants Interpolants;
|
2018-04-12 16:57:51 -04:00
|
|
|
|
|
|
|
|
Interpolants.InterpolantsVSToPS = VertexFactoryGetInterpolantsVSToPS(Input, Intermediates, VertexParameters);
|
|
|
|
|
|
|
|
|
|
return Interpolants;
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-14 15:26:31 -04:00
|
|
|
FVertexFactoryRayTracingInterpolants VertexFactoryInterpolate(FVertexFactoryRayTracingInterpolants a, float aInterp, FVertexFactoryRayTracingInterpolants b, float bInterp)
|
2018-04-12 16:57:51 -04:00
|
|
|
{
|
2021-04-14 15:26:31 -04:00
|
|
|
FVertexFactoryRayTracingInterpolants O;
|
2018-04-12 16:57:51 -04:00
|
|
|
|
2021-04-14 15:26:31 -04:00
|
|
|
INTERPOLATE_MEMBER(InterpolantsVSToPS.TangentToWorld0.xyz);
|
|
|
|
|
INTERPOLATE_MEMBER(InterpolantsVSToPS.TangentToWorld2);
|
2019-01-22 12:03:56 -05:00
|
|
|
#if INTERPOLATE_VERTEX_COLOR
|
2021-04-14 15:26:31 -04:00
|
|
|
INTERPOLATE_MEMBER(InterpolantsVSToPS.Color);
|
2019-01-22 12:03:56 -05:00
|
|
|
#endif
|
2018-04-12 16:57:51 -04:00
|
|
|
|
|
|
|
|
#if NUM_TEX_COORD_INTERPOLATORS
|
|
|
|
|
UNROLL
|
2021-07-15 10:11:35 -04:00
|
|
|
for(int tc = 0; tc < (NUM_TEX_COORD_INTERPOLATORS + 1) / 2; ++tc)
|
2018-04-12 16:57:51 -04:00
|
|
|
{
|
2021-04-14 15:26:31 -04:00
|
|
|
INTERPOLATE_MEMBER(InterpolantsVSToPS.TexCoords[tc]);
|
2018-04-12 16:57:51 -04:00
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2021-09-01 07:12:02 -04:00
|
|
|
#if VF_USE_PRIMITIVE_SCENE_DATA
|
|
|
|
|
O.InterpolantsVSToPS.PrimitiveId = a.InterpolantsVSToPS.PrimitiveId;
|
|
|
|
|
#endif
|
|
|
|
|
|
2018-04-12 16:57:51 -04:00
|
|
|
return O;
|
|
|
|
|
}
|
2021-04-14 15:26:31 -04:00
|
|
|
#endif // #if NEEDS_VERTEX_FACTORY_INTERPOLATION
|
2018-04-12 16:57:51 -04:00
|
|
|
|
|
|
|
|
float4 VertexFactoryGetTranslatedPrimitiveVolumeBounds(FVertexFactoryInterpolantsVSToPS Interpolants)
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
2018-12-11 22:25:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint VertexFactoryGetPrimitiveId(FVertexFactoryInterpolantsVSToPS Interpolants)
|
|
|
|
|
{
|
2021-09-01 07:12:02 -04:00
|
|
|
#if VF_USE_PRIMITIVE_SCENE_DATA
|
|
|
|
|
return Interpolants.PrimitiveId;
|
|
|
|
|
#else // VF_USE_PRIMITIVE_SCENE_DATA
|
2018-12-11 22:25:04 -05:00
|
|
|
return 0;
|
2021-09-01 07:12:02 -04:00
|
|
|
#endif // VF_USE_PRIMITIVE_SCENE_DATA
|
2018-12-11 22:25:04 -05:00
|
|
|
}
|
2021-01-14 02:38:46 -04:00
|
|
|
|
|
|
|
|
#include "VertexFactoryDefaultInterface.ush"
|