319 lines
10 KiB
HLSL
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" |