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

319 lines
10 KiB
HLSL

// Copyright Epic Games, Inc. All Rights Reserved.
/*=============================================================================
ParticleBeamTrailVertexFactory.hlsl: Particle vertex factory shader code.
=============================================================================*/
#include "VertexFactoryCommon.ush"
struct FVertexFactoryInput
{
float4 Position : ATTRIBUTE0;
float3 OldPosition : ATTRIBUTE1;
float4 SizeRotSubImage : ATTRIBUTE2;
float4 TexCoord : ATTRIBUTE3;
float4 Color : ATTRIBUTE4;
#if USE_DYNAMIC_PARAMETERS
float4 DynamicParameter0 : ATTRIBUTE5;
#endif //USE_DYNAMIC_PARAMETERS
VF_INSTANCED_STEREO_DECLARE_INPUT_BLOCK()
VF_MOBILE_MULTI_VIEW_DECLARE_INPUT_BLOCK()
};
struct FVertexFactoryInterpolantsVSToPS
{
TANGENTTOWORLD_INTERPOLATOR_BLOCK
#if NUM_TEX_COORD_INTERPOLATORS
float4 TexCoords[(NUM_TEX_COORD_INTERPOLATORS+1)/2] : PACKED_TEXCOORDS;
#endif
#if NEEDS_PARTICLE_COLOR
float4 Color : TEXCOORD3;
#endif
#if USE_DYNAMIC_PARAMETERS
float4 DynamicParameter0 : TEXCOORD4;
#endif //USE_DYNAMIC_PARAMETERS
};
struct FVertexFactoryIntermediates
{
/** The color of the sprite. */
float4 Color;
/** Cached primitive and instance data */
FSceneDataIntermediates SceneData;
};
FPrimitiveSceneData GetPrimitiveData(FVertexFactoryIntermediates Intermediates)
{
return Intermediates.SceneData.Primitive;
}
/** 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 UVIndex=0; UVIndex < NUM_TEX_COORD_INTERPOLATORS / 2; ++UVIndex)
{
Result.TexCoords[(UVIndex * 2) + 0] = Interpolants.TexCoords[UVIndex].xy;
Result.TexCoords[(UVIndex * 2) + 1] = Interpolants.TexCoords[UVIndex].zw;
}
#if (NUM_TEX_COORD_INTERPOLATORS & 1) == 1
Result.TexCoords[NUM_TEX_COORD_INTERPOLATORS - 1] = Interpolants.TexCoords[NUM_TEX_COORD_INTERPOLATORS / 2].xy;
#endif
#endif // NUM_TEX_COORD_INTERPOLATORS
Result.VertexColor = 1;
#if NEEDS_PARTICLE_COLOR
Result.Particle.Color = Interpolants.Color;
#endif
half3 TangentToWorld0 = Interpolants.TangentToWorld0.xyz;
half4 TangentToWorld2 = Interpolants.TangentToWorld2;
Result.TangentToWorld = AssembleTangentToWorld( TangentToWorld0, TangentToWorld2 );
Result.UnMirrored = 1;
#if LIGHTMAP_UV_ACCESS
#if NUM_TEX_COORD_INTERPOLATORS > 0
Result.LightmapUVs = Interpolants.TexCoords[0].xy;
#else
Result.LightmapUVs = 0;
#endif
#endif
Result.TwoSidedSign = 1;
#if USE_DYNAMIC_PARAMETERS
Result.Particle.DynamicParameter = Interpolants.DynamicParameter0;
#endif //USE_DYNAMIC_PARAMETERS
return Result;
}
float3 VertexFactoryGetPreviousInstanceSpacePosition(FVertexFactoryInput Input, FVertexFactoryIntermediates Intermediates);
float3 VertexFactoryGetInstanceSpacePosition(FVertexFactoryInput Input, FVertexFactoryIntermediates Intermediates);
/** 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,
bool bIsPreviousFrame = false)
{
FMaterialVertexParameters Result = MakeInitializedMaterialVertexParameters();
Result.SceneData = Intermediates.SceneData;
Result.WorldPosition = WorldPosition;
if (bIsPreviousFrame)
{
Result.PositionInstanceSpace = VertexFactoryGetPreviousInstanceSpacePosition(Input, Intermediates);
}
else
{
Result.PositionInstanceSpace = VertexFactoryGetInstanceSpacePosition(Input, Intermediates);
}
Result.PositionPrimitiveSpace = Result.PositionInstanceSpace; // No support for instancing, so instance == primitive
Result.VertexColor = Input.Color;
Result.TangentToWorld = mul(TangentToLocal, GetLocalToWorld3x3());
Result.Particle.Color = Intermediates.Color;
Result.PreSkinnedPosition = Input.Position.xyz;
Result.PreSkinnedNormal = TangentToLocal[2].xyz;
// Previous frame not handled deliberately. Lacks necessary information and
// primitives using this VF are usually transparent and hence don't output velocity
Result.PrevFrameLocalToWorld = GetPrimitiveDataFromUniformBuffer().LocalToWorld;
#if NUM_MATERIAL_TEXCOORDS_VERTEX
for(int CoordinateIndex = 0; CoordinateIndex < NUM_MATERIAL_TEXCOORDS_VERTEX; CoordinateIndex++)
{
Result.TexCoords[CoordinateIndex] = Input.TexCoord.xy;
}
#endif
#if ENABLE_NEW_HLSL_GENERATOR
EvaluateVertexMaterialAttributes(Result);
#endif
Result.LWCData = MakeMaterialLWCData(Result);
return Result;
}
float3 SafeNormalize(float3 V)
{
return V / sqrt(max(dot(V,V),0.01));
}
float4 SimulationToTranslatedWorld(float3 SimPosition)
{
if ( BeamTrailVF.bUseLocalSpace )
{
FDFMatrix Transform = GetPrimitiveDataFromUniformBuffer().LocalToWorld;
return DFTransformLocalToTranslatedWorld(SimPosition, Transform, ResolvedView.PreViewTranslation);
}
else
{
FLWCVector3 WorldPosition = MakeLWCVector3(BeamTrailVF.LWCTile, SimPosition);
FLWCVector3 TranslatedWorldPosition = LWCAdd(WorldPosition, ResolvedView.TileOffset.PreViewTranslation);
return float4(LWCToFloat(TranslatedWorldPosition), 1.0f);
}
}
void GetTangents(FVertexFactoryInput Input,out float4 Right,out float4 Up)
{
float4 Position = SimulationToTranslatedWorld(Input.Position.xyz),
OldPosition = SimulationToTranslatedWorld(Input.OldPosition.xyz);
float3 CameraDirection = -GetCameraVectorFromTranslatedWorldPosition(ResolvedView, Position.xyz),
ParticleDirection = SafeNormalize(Position.xyz - OldPosition.xyz);
float4 Right_Square = BeamTrailVF.CameraRight,
Up_Square = BeamTrailVF.CameraUp;
float4 Right_Rotated = (-1.0 * cos(Input.SizeRotSubImage.z) * Up_Square) + (sin(Input.SizeRotSubImage.z) * Right_Square),
Up_Rotated = ( sin(Input.SizeRotSubImage.z) * Up_Square) + (cos(Input.SizeRotSubImage.z) * Right_Square);
float4 Right_Velocity = float4( SafeNormalize( cross( CameraDirection, ParticleDirection ) ), 0.0 ),
Up_Velocity = float4( ParticleDirection, 0.0 );
// enum EParticleScreenAlignment
// {
// PSA_Square,
// PSA_Rectangle,
// PSA_Velocity
// };
Right = BeamTrailVF.ScreenAlignment.x > 1.5f ? Right_Velocity : Right_Rotated;
Up = BeamTrailVF.ScreenAlignment.x > 1.5f ? Up_Velocity : Up_Rotated;
}
float4 CalcWorldPosition(FVertexFactoryInput Input)
{
return SimulationToTranslatedWorld(Input.Position.xyz);
}
/** derive basis vectors */
float3x3 CalcTangentBasis(FVertexFactoryInput Input)
{
float4 Right,
Up;
GetTangents(Input,Right,Up);
return float3x3(
Right.xyz,
Up.xyz,
-normalize(cross(Right.xyz,Up.xyz))
);
}
FVertexFactoryIntermediates GetVertexFactoryIntermediates(FVertexFactoryInput Input)
{
FVertexFactoryIntermediates Intermediates;
Intermediates.SceneData = VF_GPUSCENE_GET_INTERMEDIATES(Input);
Intermediates.Color = Input.Color;
return Intermediates;
}
float4 VertexFactoryGetWorldPosition(FVertexFactoryInput Input, FVertexFactoryIntermediates Intermediates)
{
return CalcWorldPosition(Input);
}
float3 VertexFactoryGetInstanceSpacePosition(FVertexFactoryInput Input, FVertexFactoryIntermediates Intermediates)
{
return Input.Position.xyz;
}
float3 VertexFactoryGetWorldNormal(FVertexFactoryInput Input, FVertexFactoryIntermediates Intermediates)
{
return CalcTangentBasis(Input)[2];
}
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;
#if NUM_TEX_COORD_INTERPOLATORS
float2 CustomizedUVs[NUM_TEX_COORD_INTERPOLATORS];
GetMaterialCustomizedUVs(VertexParameters, CustomizedUVs);
GetCustomInterpolators(VertexParameters, CustomizedUVs);
UNROLL
for (int UVIndex=0; UVIndex < NUM_TEX_COORD_INTERPOLATORS / 2; ++UVIndex)
{
Interpolants.TexCoords[UVIndex].xy = CustomizedUVs[UVIndex * 2 + 0];
Interpolants.TexCoords[UVIndex].zw = CustomizedUVs[UVIndex * 2 + 1];
}
#if (NUM_TEX_COORD_INTERPOLATORS & 1) == 1
Interpolants.TexCoords[NUM_TEX_COORD_INTERPOLATORS / 2].xy = CustomizedUVs[NUM_TEX_COORD_INTERPOLATORS - 1];
Interpolants.TexCoords[NUM_TEX_COORD_INTERPOLATORS / 2].zw = 0.0f;
#endif
#endif // NUM_MATERIAL_TEXCOORDS
#if NEEDS_PARTICLE_COLOR
Interpolants.Color = Intermediates.Color;
#endif
#if USE_DYNAMIC_PARAMETERS
Interpolants.DynamicParameter0 = Input.DynamicParameter0;
#endif //USE_DYNAMIC_PARAMETERS
float3x3 TangentToLocal = CalcTangentBasis(Input);
float3x3 TangentToWorld = mul(TangentToLocal, GetLocalToWorld3x3());
Interpolants.TangentToWorld0.xyz = TangentToWorld[0];
Interpolants.TangentToWorld0.w = 0;
Interpolants.TangentToWorld2 = float4(TangentToWorld[2], sign(determinant(TangentToLocal)));
return Interpolants;
}
float4 VertexFactoryGetPreviousWorldPosition(FVertexFactoryInput Input, FVertexFactoryIntermediates Intermediates)
{
return VertexFactoryGetWorldPosition(Input, Intermediates);
}
// local position relative to instance
float3 VertexFactoryGetPreviousInstanceSpacePosition(FVertexFactoryInput Input, FVertexFactoryIntermediates Intermediates)
{
return Input.Position.xyz;
}
/**
* 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 CalcTangentBasis(Input);
}
float4 VertexFactoryGetTranslatedPrimitiveVolumeBounds(FVertexFactoryInterpolantsVSToPS Interpolants)
{
return 0;
}
uint VertexFactoryGetPrimitiveId(FVertexFactoryInterpolantsVSToPS Interpolants)
{
return 0;
}
#include "VertexFactoryDefaultInterface.ush"