You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
ViewWorldOrigin -> WorldViewOrigin CameraWorldOrigin -> WorldCameraOrigin CameraTranslatedWorldOrigin -> TranslatedWorldCameraOrigin CameraWorldOriginDelta -> WorldCameraMovementSinceLastFrame PrevCameraWorldOrigin -> PrevWorldCameraOrigin PrevViewWorldOrigin -> PrevWorldViewOrigin #code_review: Martin.Mittring [CL 2666624 by Guillaume Abadie in Main branch]
562 lines
19 KiB
Plaintext
562 lines
19 KiB
Plaintext
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
|
|
|
|
/*=============================================================================
|
|
ParticleSpriteVertexFactory.hlsl: Particle vertex factory shader code.
|
|
Shared by standard sprite particles and SubUV sprite particles.
|
|
=============================================================================*/
|
|
|
|
#include "VertexFactoryCommon.usf"
|
|
#include "ParticleVertexFactoryCommon.usf"
|
|
|
|
// These are only enabled for SM5 due to limited interpolators elsewhere
|
|
#define USE_PARTICLE_LIGHTING_OFFSET (FEATURE_LEVEL >= FEATURE_LEVEL_SM5 && !MATERIAL_SHADINGMODEL_UNLIT)
|
|
#define USE_PARTICLE_POSITION (FEATURE_LEVEL >= FEATURE_LEVEL_SM5 && NEEDS_PARTICLE_POSITION)
|
|
#define USE_PARTICLE_VELOCITY (FEATURE_LEVEL >= FEATURE_LEVEL_SM5 && NEEDS_PARTICLE_VELOCITY)
|
|
#define USE_PARTICLE_TIME (FEATURE_LEVEL >= FEATURE_LEVEL_SM5 && NEEDS_PARTICLE_TIME)
|
|
#define USE_PARTICLE_SIZE (FEATURE_LEVEL >= FEATURE_LEVEL_SM5 && NEEDS_PARTICLE_SIZE)
|
|
|
|
// We don't compute a tangent basis in ES2 to save shader instructions.
|
|
#define NEEDS_TANGENT_BASIS (FEATURE_LEVEL >= FEATURE_LEVEL_SM4)
|
|
|
|
struct FVertexFactoryInput
|
|
{
|
|
float4 Position : ATTRIBUTE0;
|
|
float4 OldPosition : ATTRIBUTE1;
|
|
float4 SizeRotSubImage : ATTRIBUTE2;
|
|
float4 Color : ATTRIBUTE3;
|
|
#if USE_DYNAMIC_PARAMETERS
|
|
float4 DynamicParameter : ATTRIBUTE5;
|
|
#endif //USE_DYNAMIC_PARAMETERS
|
|
float2 TexCoord : ATTRIBUTE4;
|
|
};
|
|
|
|
struct FVertexFactoryInterpolantsVSToPS
|
|
{
|
|
#if NEEDS_TANGENT_BASIS
|
|
// First row of the tangent to world matrix, Interp_Sizer used by SUBUV_PARTICLES in w
|
|
float4 TangentToWorld0AndInterp_Sizer : TANGENTTOWORLD0;
|
|
// Last row of the tangent to world matrix in xyz
|
|
float4 TangentToWorld2 : TANGENTTOWORLD2;
|
|
#else
|
|
float SubImageLerp : TEXCOORD0;
|
|
#endif
|
|
|
|
#if USE_DYNAMIC_PARAMETERS
|
|
float4 DynamicParameter : TEXCOORD1;
|
|
#endif //USE_DYNAMIC_PARAMETERS
|
|
|
|
#if NEEDS_PARTICLE_COLOR
|
|
float4 Color : TEXCOORD2;
|
|
#endif
|
|
|
|
#if NUM_MATERIAL_TEXCOORDS
|
|
float4 TexCoords[(NUM_MATERIAL_TEXCOORDS + 1) / 2] : TEXCOORD3;
|
|
#endif
|
|
|
|
//Not sure this is actually being used now and it's awkward to slot in now we're supporting custom UVs so I'm just giving this its own interpolant.
|
|
#if LIGHTMAP_UV_ACCESS
|
|
float2 LightMapUVs : LIGHTMAP_UVS;
|
|
#endif
|
|
|
|
#if USE_PARTICLE_SUBUVS
|
|
float4 ParticleSubUVs : PARTICLE_SUBUVS;
|
|
#endif
|
|
|
|
#if USE_PARTICLE_POSITION
|
|
float4 ParticlePositionAndSize : PARTICLE_POSITION;
|
|
#endif
|
|
|
|
#if USE_PARTICLE_VELOCITY
|
|
float4 ParticleVelocity : PARTICLE_VELOCITY;
|
|
#endif
|
|
|
|
#if USE_PARTICLE_TIME
|
|
float ParticleTime : PARTICLE_TIME;
|
|
#endif
|
|
|
|
#if USE_PARTICLE_LIGHTING_OFFSET
|
|
float3 LightingPositionOffset : PARTICLE_LIGHTING_OFFSET;
|
|
#endif
|
|
|
|
#if USE_PARTICLE_SIZE
|
|
float2 ParticleSize : PARTICLE_SIZE;
|
|
#endif
|
|
};
|
|
|
|
struct FVertexFactoryIntermediates
|
|
{
|
|
/** The position of the particle in non-translated world space. */
|
|
float3 ParticleWorldPosition;
|
|
/** The position of the vertex in translated world space. */
|
|
float3 VertexWorldPosition;
|
|
/** Particle (non-translated) world space position and size. */
|
|
float4 PositionAndSize;
|
|
|
|
#if USE_PARTICLE_LIGHTING_OFFSET
|
|
float3 LightingPositionOffset;
|
|
#endif
|
|
|
|
/** The texture coordinate at this vertex. */
|
|
float4 TexCoord;
|
|
/** The sprite tangent in world space (+V). */
|
|
float3 TangentUp;
|
|
/** The sprite tangent in world space (+U). */
|
|
float3 TangentRight;
|
|
/** The color of the sprite. */
|
|
float4 Color;
|
|
/** The velocity of the particle, XYZ: direction, W: speed. */
|
|
float4 ParticleVelocity;
|
|
/** Dynamic parameter. */
|
|
float4 DynamicParameter;
|
|
/** The sub-image lerp. */
|
|
float SubImageLerp;
|
|
/** Relative time. */
|
|
float RelativeTime;
|
|
/** Transform from tangent space to local space. */
|
|
float3x3 TangentToLocal;
|
|
/** Size of the particle */
|
|
float2 ParticleSize;
|
|
};
|
|
|
|
#if NUM_MATERIAL_TEXCOORDS
|
|
bool UVIndexUseZW(int UVIndex)
|
|
{
|
|
#if COMPILER_GLSL_ES2
|
|
return (frac((float)UVIndex / 2.0f) == 0.5f);
|
|
#else
|
|
return (UVIndex % 2) != 0;
|
|
#endif
|
|
}
|
|
|
|
float2 GetUV(FVertexFactoryInterpolantsVSToPS Interpolants, int UVIndex)
|
|
{
|
|
float4 UVVector = Interpolants.TexCoords[UVIndex / 2];
|
|
return UVIndexUseZW(UVIndex) ? UVVector.zw : UVVector.xy;
|
|
}
|
|
|
|
void SetUV(inout FVertexFactoryInterpolantsVSToPS Interpolants, int UVIndex, float2 InValue)
|
|
{
|
|
FLATTEN
|
|
if (UVIndexUseZW(UVIndex))
|
|
{
|
|
Interpolants.TexCoords[UVIndex / 2].zw = InValue;
|
|
}
|
|
else
|
|
{
|
|
Interpolants.TexCoords[UVIndex / 2].xy = InValue;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/** Converts from vertex factory specific interpolants to a FMaterialPixelParameters, which is used by material inputs. */
|
|
FMaterialPixelParameters GetMaterialPixelParameters(FVertexFactoryInterpolantsVSToPS Interpolants, float4 PixelPosition)
|
|
{
|
|
// GetMaterialPixelParameters is responsible for fully initializing the result
|
|
FMaterialPixelParameters Result = MakeInitializedMaterialPixelParameters();
|
|
|
|
#if NUM_MATERIAL_TEXCOORDS
|
|
UNROLL
|
|
for (int CoordinateIndex = 0; CoordinateIndex < NUM_MATERIAL_TEXCOORDS; CoordinateIndex++)
|
|
{
|
|
Result.TexCoords[CoordinateIndex] = GetUV(Interpolants, CoordinateIndex);
|
|
}
|
|
#endif // NUM_MATERIAL_TEXCOORDS
|
|
|
|
Result.VertexColor = 1;
|
|
|
|
#if NEEDS_TANGENT_BASIS
|
|
half4 TangentToWorld0 = Interpolants.TangentToWorld0AndInterp_Sizer;
|
|
half4 TangentToWorld2 = Interpolants.TangentToWorld2;
|
|
float SubImageLerp = Interpolants.TangentToWorld0AndInterp_Sizer.w;
|
|
|
|
#if GENERATE_SPHERICAL_PARTICLE_NORMALS && USE_PARTICLE_POSITION
|
|
Result.TangentToWorld = GetSphericalParticleNormal(PixelPosition.xyz + View.WorldCameraOrigin, Interpolants.ParticlePositionAndSize.xyz, Interpolants.ParticlePositionAndSize.w);
|
|
#else
|
|
Result.TangentToWorld = AssembleTangentToWorld(TangentToWorld0.xyz, TangentToWorld2);
|
|
#endif
|
|
#else
|
|
float SubImageLerp = Interpolants.SubImageLerp;
|
|
#endif
|
|
|
|
Result.UnMirrored = 1;
|
|
Result.Particle.MacroUV = SpriteVF.MacroUVParameters;
|
|
|
|
#if NEEDS_PARTICLE_COLOR
|
|
Result.Particle.Color = Interpolants.Color;
|
|
#endif
|
|
|
|
#if USE_DYNAMIC_PARAMETERS
|
|
Result.Particle.DynamicParameter = Interpolants.DynamicParameter;
|
|
#endif //USE_DYNAMIC_PARAMETERS
|
|
|
|
#if USE_PARTICLE_POSITION
|
|
Result.Particle.PositionAndSize = Interpolants.ParticlePositionAndSize;
|
|
#endif
|
|
|
|
#if USE_PARTICLE_VELOCITY
|
|
Result.Particle.Velocity = Interpolants.ParticleVelocity;
|
|
#endif
|
|
|
|
#if USE_PARTICLE_TIME
|
|
Result.Particle.RelativeTime = Interpolants.ParticleTime;
|
|
#endif
|
|
|
|
Result.Particle.MotionBlurFade = 1.0f;
|
|
|
|
|
|
#if USE_PARTICLE_LIGHTING_OFFSET
|
|
Result.LightingPositionOffset = Interpolants.LightingPositionOffset;
|
|
#endif
|
|
|
|
#if USE_PARTICLE_SUBUVS
|
|
Result.Particle.SubUVCoords[0] = Interpolants.ParticleSubUVs.xy;
|
|
Result.Particle.SubUVCoords[1] = Interpolants.ParticleSubUVs.zw;
|
|
Result.Particle.SubUVLerp = SubImageLerp;
|
|
#endif
|
|
|
|
#if LIGHTMAP_UV_ACCESS
|
|
Result.LightmapUVs = Interpolants.LightMapUVs;
|
|
#endif
|
|
|
|
#if USE_PARTICLE_SIZE
|
|
Result.Particle.Size = Interpolants.ParticleSize;
|
|
#endif
|
|
|
|
Result.TwoSidedSign = 1;
|
|
return Result;
|
|
}
|
|
|
|
/** 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.WorldPosition = WorldPosition;
|
|
Result.VertexColor = Input.Color;
|
|
Result.TangentToWorld = mul(TangentToLocal, GetLocalToWorld3x3());
|
|
Result.Particle.MacroUV = SpriteVF.MacroUVParameters;
|
|
Result.Particle.Color = Intermediates.Color;
|
|
Result.Particle.MotionBlurFade = 1.0f;
|
|
|
|
#if USE_DYNAMIC_PARAMETERS
|
|
Result.Particle.DynamicParameter = Intermediates.DynamicParameter;
|
|
#endif //USE_DYNAMIC_PARAMETERS
|
|
|
|
#if USE_PARTICLE_POSITION
|
|
Result.Particle.PositionAndSize = Intermediates.PositionAndSize;
|
|
#endif
|
|
|
|
#if USE_PARTICLE_VELOCITY
|
|
Result.Particle.Velocity = Intermediates.ParticleVelocity;
|
|
#endif
|
|
|
|
#if USE_PARTICLE_TIME
|
|
Result.Particle.RelativeTime = Intermediates.RelativeTime;
|
|
#endif
|
|
|
|
#if NUM_MATERIAL_TEXCOORDS_VERTEX
|
|
#if NUM_MATERIAL_TEXCOORDS_VERTEX >= 1
|
|
Result.TexCoords[0] = Intermediates.TexCoord.xy;
|
|
#if NUM_MATERIAL_TEXCOORDS_VERTEX >= 2
|
|
Result.TexCoords[1] = Intermediates.TexCoord.zw;
|
|
#endif // >= 2
|
|
#endif // >= 1
|
|
#endif //NUM_MATERIAL_TEXCOORDS_VERTEX
|
|
|
|
#if USE_PARTICLE_SUBUVS
|
|
Result.Particle.SubUVCoords[0] = Intermediates.TexCoord.xy;
|
|
Result.Particle.SubUVCoords[1] = Intermediates.TexCoord.zw;
|
|
#endif
|
|
|
|
#if USE_PARTICLE_SIZE
|
|
Result.Particle.Size = Intermediates.ParticleSize;
|
|
#endif
|
|
return Result;
|
|
}
|
|
|
|
void GetLightMapCoordinates(FVertexFactoryInterpolantsVSToPS Interpolants, out float2 LightmapUV0, out float2 LightmapUV1)
|
|
{
|
|
LightmapUV0 = LightmapUV1 = 0;
|
|
}
|
|
|
|
half2 GetShadowMapCoordinate(FVertexFactoryInterpolantsVSToPS Interpolants)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
float3 SafeNormalize(float3 V)
|
|
{
|
|
return V * rsqrt(max(dot(V,V),0.01));
|
|
}
|
|
|
|
void GetTangents(FVertexFactoryInput Input, float3 WorldPosition, float3 OldWorldPosition, out float3 OutRight, out float3 OutUp)
|
|
{
|
|
// Select camera up/right vectors.
|
|
float3 CameraRight = lerp(View.ViewRight, SpriteVF.AxisLockRight.xyz, SpriteVF.AxisLockRight.w);
|
|
float3 CameraUp = lerp(-View.ViewUp, SpriteVF.AxisLockUp.xyz, SpriteVF.AxisLockUp.w);
|
|
|
|
// Determine the vector from the particle to the camera and the particle's movement direction.
|
|
float3 CameraDirection = SafeNormalize(View.WorldCameraOrigin - WorldPosition.xyz);
|
|
float3 ParticleDirection = SafeNormalize(WorldPosition.xyz - OldWorldPosition.xyz);
|
|
|
|
// Tangent vectors for PSA_Velocity.
|
|
float3 Right_Velocity = SafeNormalize(cross(CameraDirection, ParticleDirection));
|
|
float3 Up_Velocity = -ParticleDirection;
|
|
|
|
// Tangent vectors for rotation locked about an axis.
|
|
float3 Right_AxisRot = SpriteVF.AxisLockRight.xyz;
|
|
float3 Up_AxisRot = -SafeNormalize(cross(Right_AxisRot,CameraDirection));
|
|
|
|
// Tangent vectors for camera facing position.
|
|
float3 Right_FacingCameraPosition = SafeNormalize(cross(CameraDirection,float3(0,0,1)));
|
|
float3 Up_FacingCameraPosition = cross(CameraDirection, Right_FacingCameraPosition);
|
|
|
|
// Select the appropriate tangents.
|
|
// The TangentSelector values are as follows:
|
|
// x - multiplied by the standard camera right/up values
|
|
// y - multiplied by the velocity right/up values
|
|
// z - multiplied by the axis rotation right/up values
|
|
// The multiplies are summed together to give the final right/up
|
|
float3 Right_Square = (CameraRight.xyz * SpriteVF.TangentSelector.x) +
|
|
(Right_Velocity * SpriteVF.TangentSelector.y) +
|
|
(Right_AxisRot * SpriteVF.TangentSelector.z) +
|
|
(Right_FacingCameraPosition * SpriteVF.TangentSelector.w);
|
|
float3 Up_Square = (CameraUp.xyz * SpriteVF.TangentSelector.x) +
|
|
(Up_Velocity * SpriteVF.TangentSelector.y) +
|
|
(Up_AxisRot * SpriteVF.TangentSelector.z) +
|
|
(Up_FacingCameraPosition * SpriteVF.TangentSelector.w);
|
|
|
|
// Determine the angle of rotation.
|
|
float SinRotation;
|
|
float CosRotation;
|
|
const float RotationScale = SpriteVF.RotationScale;
|
|
const float RotationBias = SpriteVF.RotationBias;
|
|
const float SpriteRotation = Input.SizeRotSubImage.z * RotationScale + RotationBias;
|
|
sincos(SpriteRotation, SinRotation, CosRotation);
|
|
|
|
// Rotate the sprite to determine final tangents.
|
|
OutRight = SinRotation * Up_Square + CosRotation * Right_Square;
|
|
OutUp = CosRotation * Up_Square - SinRotation * Right_Square;
|
|
}
|
|
|
|
/** derive basis vectors */
|
|
float3x3 CalcTangentBasis(FVertexFactoryIntermediates Intermediates)
|
|
{
|
|
#if NEEDS_TANGENT_BASIS
|
|
// Using camera facing TangentX and TangentY. The resulting tangent basis is not orthonormal with anything other than ENM_CameraFacing,
|
|
// So there are artifacts with tangent space calculations like the TransformVector node,
|
|
// But this allows lighting based on a world space shape via the normal while still having normal maps camera aligned.
|
|
float3x3 Result;
|
|
Result[0] = Intermediates.TangentRight;
|
|
Result[1] = Intermediates.TangentUp;
|
|
|
|
// ENM_CameraFacing
|
|
//@todo - use static branching
|
|
if (SpriteVF.NormalsType < .5f)
|
|
{
|
|
Result[2] = normalize(cross(Result[0],Result[1]));
|
|
}
|
|
// ENM_Spherical
|
|
else if (SpriteVF.NormalsType < 1.5f)
|
|
{
|
|
float3 TangentZ = normalize(Intermediates.ParticleWorldPosition.xyz - SpriteVF.NormalsSphereCenter.xyz);
|
|
Result[2] = TangentZ;
|
|
}
|
|
// ENM_Cylindrical
|
|
else
|
|
{
|
|
float3 ClosestPointOnCylinder = SpriteVF.NormalsSphereCenter.xyz + dot(SpriteVF.NormalsCylinderUnitDirection.xyz, Intermediates.ParticleWorldPosition.xyz - SpriteVF.NormalsSphereCenter.xyz) * SpriteVF.NormalsCylinderUnitDirection.xyz;
|
|
float3 TangentZ = normalize(Intermediates.ParticleWorldPosition.xyz - ClosestPointOnCylinder);
|
|
Result[2] = TangentZ;
|
|
}
|
|
|
|
return Result;
|
|
#else
|
|
// Return the identity matrix.
|
|
return float3x3(1,0,0,0,1,0,0,0,1);
|
|
#endif
|
|
}
|
|
|
|
FVertexFactoryIntermediates GetVertexFactoryIntermediates(FVertexFactoryInput Input)
|
|
{
|
|
FVertexFactoryIntermediates Intermediates = (FVertexFactoryIntermediates)0;
|
|
|
|
// World position.
|
|
float4 ParticleWorldPosition = mul(float4(Input.Position.xyz,1), Primitive.LocalToWorld);
|
|
float4 ParticleOldWorldPosition = mul(float4(Input.OldPosition.xyz,1), Primitive.LocalToWorld);
|
|
Intermediates.ParticleWorldPosition = ParticleWorldPosition.xyz;
|
|
|
|
// Tangents.
|
|
float3 Right,Up;
|
|
GetTangents(Input,ParticleWorldPosition.xyz,ParticleOldWorldPosition.xyz,Right,Up);
|
|
Intermediates.TangentUp = Up;
|
|
Intermediates.TangentRight = Right;
|
|
|
|
// Vertex position.
|
|
float4 VertexWorldPosition = float4(ParticleWorldPosition.xyz + View.PreViewTranslation,1);
|
|
float2 Size = abs(Input.SizeRotSubImage.xy);
|
|
VertexWorldPosition += Size.x * (Input.TexCoord.x + SpriteVF.PivotOffset.x) * float4(Right,0);
|
|
VertexWorldPosition += Size.y * (Input.TexCoord.y + SpriteVF.PivotOffset.y) * float4(Up,0);
|
|
Intermediates.VertexWorldPosition = VertexWorldPosition.xyz;
|
|
|
|
//We encode the UV flip in the sign of the size data.
|
|
float2 UVFlip = sign(Input.SizeRotSubImage.xy);
|
|
float2 FlippedUV = Input.TexCoord.xy;
|
|
FlippedUV.x = UVFlip.x < 0.0 ? 1.0 - FlippedUV.x : FlippedUV.x;
|
|
FlippedUV.y = UVFlip.y < 0.0 ? 1.0 - FlippedUV.y : FlippedUV.y;
|
|
|
|
// SubUV.
|
|
float SubImageIndex = Input.SizeRotSubImage.w;
|
|
float SubImageLerp = frac(SubImageIndex);
|
|
float SubImageA = SubImageIndex - SubImageLerp;
|
|
float SubImageB = SubImageA + 1;
|
|
float SubImageAH = fmod( SubImageA, SpriteVF.SubImageSize.x );
|
|
float SubImageBH = fmod( SubImageB, SpriteVF.SubImageSize.x );
|
|
float SubImageAV = floor( SubImageA * SpriteVF.SubImageSize.z );
|
|
float SubImageBV = floor( SubImageB * SpriteVF.SubImageSize.z );
|
|
Intermediates.TexCoord.xy = (float2( SubImageAH, SubImageAV ) + FlippedUV) * SpriteVF.SubImageSize.zw ;
|
|
Intermediates.TexCoord.zw = (float2( SubImageBH, SubImageBV ) + FlippedUV) * SpriteVF.SubImageSize.zw ;
|
|
Intermediates.SubImageLerp = SubImageLerp;
|
|
|
|
Intermediates.Color = Input.Color;
|
|
|
|
#if USE_DYNAMIC_PARAMETERS
|
|
Intermediates.DynamicParameter = Input.DynamicParameter;
|
|
#endif //USE_DYNAMIC_PARAMETERS
|
|
|
|
|
|
#if USE_PARTICLE_POSITION
|
|
float ParticleRadius = .5f * min(Input.SizeRotSubImage.x, Input.SizeRotSubImage.y);
|
|
Intermediates.PositionAndSize = float4(ParticleWorldPosition.xyz, ParticleRadius);
|
|
#endif
|
|
|
|
#if USE_PARTICLE_VELOCITY
|
|
float3 ParticleVelocity = (ParticleWorldPosition - ParticleOldWorldPosition) * SpriteVF.InvDeltaSeconds;
|
|
Intermediates.ParticleVelocity.xyz = normalize(ParticleVelocity);
|
|
Intermediates.ParticleVelocity.w = length(ParticleVelocity);
|
|
#endif
|
|
|
|
#if USE_PARTICLE_TIME
|
|
Intermediates.RelativeTime = Input.Position.w;
|
|
#endif
|
|
|
|
Intermediates.TangentToLocal = CalcTangentBasis(Intermediates);
|
|
|
|
#if USE_PARTICLE_LIGHTING_OFFSET
|
|
// Hash function based on the particle ID to generate a uniformly distributed 3d offset
|
|
float3 RandomParticleOffset = frac(Square(Input.OldPosition.w + 10) * float3(1361.456345, 2333.578, 3623.983)) * 2 - 1;
|
|
Intermediates.LightingPositionOffset = .5f * View.TranslucencyLightingVolumeInvSize[0].w * RandomParticleOffset;
|
|
#endif
|
|
|
|
#if USE_PARTICLE_SIZE
|
|
Intermediates.ParticleSize = Size;
|
|
#endif
|
|
|
|
return Intermediates;
|
|
}
|
|
|
|
float4 VertexFactoryGetWorldPosition(FVertexFactoryInput Input, FVertexFactoryIntermediates Intermediates)
|
|
{
|
|
return float4(Intermediates.VertexWorldPosition,1);
|
|
}
|
|
|
|
float4 VertexFactoryGetRasterizedWorldPosition(FVertexFactoryInput Input, FVertexFactoryIntermediates Intermediates, float4 TranslatedWorldPosition)
|
|
{
|
|
#if SPHERICAL_PARTICLE_OPACITY
|
|
// For particles using spherical opacity, move the quad toward the viewer so that it lies in front of the sphere defined by the particle
|
|
// This avoids opaque objects intersecting the particle from causing clipping artifacts due to depth testing
|
|
// The downside is that the particle will clip the near plane sooner
|
|
|
|
float Radius = .5f * min(Input.SizeRotSubImage.x, Input.SizeRotSubImage.y);
|
|
return ReprojectPosition(TranslatedWorldPosition, Radius);
|
|
#else
|
|
return TranslatedWorldPosition;
|
|
#endif
|
|
}
|
|
|
|
FVertexFactoryInterpolantsVSToPS VertexFactoryGetInterpolantsVSToPS(FVertexFactoryInput Input, FVertexFactoryIntermediates Intermediates, FMaterialVertexParameters VertexParameters)
|
|
{
|
|
FVertexFactoryInterpolantsVSToPS Interpolants;
|
|
|
|
// Initialize the whole struct to 0
|
|
Interpolants = (FVertexFactoryInterpolantsVSToPS)0;
|
|
|
|
#if NUM_MATERIAL_TEXCOORDS
|
|
|
|
float2 CustomizedUVs[NUM_MATERIAL_TEXCOORDS];
|
|
GetMaterialCustomizedUVs(VertexParameters, CustomizedUVs);
|
|
|
|
UNROLL
|
|
for (int CoordinateIndex = 0; CoordinateIndex < NUM_MATERIAL_TEXCOORDS; CoordinateIndex++)
|
|
{
|
|
SetUV(Interpolants, CoordinateIndex, CustomizedUVs[CoordinateIndex]);
|
|
}
|
|
#endif
|
|
|
|
#if LIGHTMAP_UV_ACCESS
|
|
Interpolants.LightMapUVs = Intermediates.TexCoord.xy;
|
|
#endif
|
|
|
|
#if USE_PARTICLE_SUBUVS
|
|
Interpolants.ParticleSubUVs.xy = VertexParameters.Particle.SubUVCoords[0];
|
|
Interpolants.ParticleSubUVs.zw = VertexParameters.Particle.SubUVCoords[1];
|
|
#endif
|
|
|
|
#if NEEDS_TANGENT_BASIS
|
|
// Calculate the transform from tangent to world space.
|
|
// Note that "local" space for particles is actually oriented in world space! Therefore no rotation is needed.
|
|
float3x3 TangentToWorld = Intermediates.TangentToLocal;
|
|
|
|
Interpolants.TangentToWorld0AndInterp_Sizer.xyz = TangentToWorld[0];
|
|
Interpolants.TangentToWorld0AndInterp_Sizer.w = Intermediates.SubImageLerp;
|
|
Interpolants.TangentToWorld2 = float4(TangentToWorld[2], sign(determinant(Intermediates.TangentToLocal)));
|
|
#else
|
|
Interpolants.SubImageLerp = Intermediates.SubImageLerp;
|
|
#endif
|
|
|
|
#if NEEDS_PARTICLE_COLOR
|
|
Interpolants.Color = Intermediates.Color;
|
|
#endif
|
|
|
|
#if USE_DYNAMIC_PARAMETERS
|
|
Interpolants.DynamicParameter = Intermediates.DynamicParameter;
|
|
#endif //USE_DYNAMIC_PARAMETERS
|
|
|
|
#if USE_PARTICLE_POSITION
|
|
Interpolants.ParticlePositionAndSize = Intermediates.PositionAndSize;
|
|
#endif
|
|
|
|
#if USE_PARTICLE_VELOCITY
|
|
Interpolants.ParticleVelocity = Intermediates.ParticleVelocity;
|
|
#endif
|
|
|
|
#if USE_PARTICLE_TIME
|
|
Interpolants.ParticleTime = Intermediates.RelativeTime;
|
|
#endif
|
|
|
|
#if USE_PARTICLE_LIGHTING_OFFSET
|
|
Interpolants.LightingPositionOffset = Intermediates.LightingPositionOffset;
|
|
#endif
|
|
|
|
#if USE_PARTICLE_SIZE
|
|
Interpolants.ParticleSize = Intermediates.ParticleSize;
|
|
#endif
|
|
|
|
return Interpolants;
|
|
}
|
|
|
|
float4 VertexFactoryGetPreviousWorldPosition(FVertexFactoryInput Input, FVertexFactoryIntermediates Intermediates)
|
|
{
|
|
return VertexFactoryGetWorldPosition(Input, Intermediates);
|
|
}
|
|
|
|
/**
|
|
* 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;
|
|
}
|