| /*============================================================================= | |
| ParticleSpriteVertexFactory.hlsl: Particle vertex factory shader code. | |
| Shared by standard sprite particles and SubUV sprite particles. | |
| Copyright 1998-2008 Epic Games, Inc. All Rights Reserved. | |
| =============================================================================*/ | |
| float4 CameraWorldPosition; | |
| float4 CameraRight; | |
| float4 CameraUp; | |
| float4 ScreenAlignment; | |
| float4x4 LocalToWorld; | |
| // The source index is which entry in the AxisRotationVectors array is the 'source'. | |
| float AxisRotationVectorSourceIndex; | |
| // The code assumes: | |
| // the right vector will be in slot 0. | |
| // the up vector will be in slot 1. | |
| float4 AxisRotationVectors[NUM_AXIS_ROTATION_VECTORS]; | |
| // The result scalars are used to determine which method is being used. | |
| // The 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 ParticleUpRightResultScalars; | |
| struct FVertexFactoryInput | |
| { | |
| float4 Position : POSITION; | |
| float4 OldPosition : NORMAL; | |
| float3 Size : TANGENT; | |
| float2 TexCoord : TEXCOORD0; | |
| float Rotation : BLENDWEIGHT0; | |
| #if SUBUV_PARTICLES | |
| float2 TexCoord1 : TEXCOORD1; | |
| float4 Interp_Sizer : TEXCOORD2; | |
| float4 Color : TEXCOORD3; | |
| #else //#if SUBUV_PARTICLES | |
| float4 Color : TEXCOORD1; | |
| #endif //#if SUBUV_PARTICLES | |
| }; | |
| struct FVertexFactoryInterpolants | |
| { | |
| #if WORLD_COORDS | |
| // xyz=normal w=determinant | |
| float4 TangentBasisNormal : COLOR0; | |
| float3 TangentBasisTangent : COLOR1; | |
| #endif | |
| float2 TexCoord : TEXCOORD0; | |
| #if SUBUV_PARTICLES | |
| float2 TexCoord1 : TEXCOORD1; | |
| float4 Interp_Sizer : TEXCOORD2; | |
| float4 Color : TEXCOORD3; | |
| #else //#if SUBUV_PARTICLES | |
| float4 Color : TEXCOORD1; | |
| #endif //#if SUBUV_PARTICLES | |
| }; | |
| FMaterialParameters GetMaterialParameters(FVertexFactoryInterpolants Interpolants) | |
| { | |
| FMaterialParameters Result; | |
| #if NUM_MATERIAL_TEXCOORDS | |
| #if SUBUV_PARTICLES | |
| #if NUM_MATERIAL_TEXCOORDS >= 1 | |
| Result.TexCoords[0] = Interpolants.TexCoord; | |
| #if NUM_MATERIAL_TEXCOORDS >= 2 | |
| Result.TexCoords[1] = Interpolants.TexCoord1; | |
| #if NUM_MATERIAL_TEXCOORDS >= 3 | |
| Result.TexCoords[2] = Interpolants.Interp_Sizer.xy; | |
| #endif // >= 3 | |
| #endif // >= 2 | |
| #endif // >= 1 | |
| #if NUM_MATERIAL_TEXCOORDS > 3 | |
| for(int CoordinateIndex = 3;CoordinateIndex < NUM_MATERIAL_TEXCOORDS;CoordinateIndex++) | |
| Result.TexCoords[CoordinateIndex] = Interpolants.TexCoord; | |
| #endif // > 3 | |
| #else //#if SUBUV_PARTICLES | |
| for(int CoordinateIndex = 0;CoordinateIndex < NUM_MATERIAL_TEXCOORDS;CoordinateIndex++) | |
| Result.TexCoords[CoordinateIndex] = Interpolants.TexCoord; | |
| #endif //#if SUBUV_PARTICLES | |
| #endif //#if NUM_MATERIAL_TEXCOORDS | |
| Result.VertexColor = Interpolants.Color; | |
| Result.TangentNormal = 0; | |
| Result.TangentCameraVector = 0; | |
| Result.TangentReflectionVector = 0; | |
| Result.TangentLightVector = 0; | |
| Result.ScreenPosition = 0; | |
| #if WORLD_COORDS | |
| Result.TangentBasisInverse = CalcInvTangentBasis(Interpolants.TangentBasisNormal,Interpolants.TangentBasisTangent); | |
| #endif | |
| return Result; | |
| } | |
| #if !VERTEX_LIGHTMAP // AJS: If this is an emissive+vertex light-map shader, we can save an interpolator by skipping the light-map coordinate. | |
| float2 GetLightMapCoordinate(FVertexFactoryInterpolants Interpolants) | |
| { | |
| #if SUBUV_PARTICLES | |
| return Interpolants.TexCoord[0]; | |
| #else //#if SUBUV_PARTICLES | |
| return Interpolants.TexCoord; | |
| #endif //#if SUBUV_PARTICLES | |
| } | |
| #endif //#if !VERTEX_LIGHTMAP | |
| float3 SafeNormalize(float3 V) | |
| { | |
| return V / sqrt(max(dot(V,V),0.01)); | |
| } | |
| void GetTangents(FVertexFactoryInput Input,out float4 Right,out float4 Up) | |
| { | |
| float4 Position = MulMatrix(LocalToWorld, Input.Position), | |
| OldPosition = MulMatrix(LocalToWorld, Input.OldPosition); | |
| float3 CameraDirection = SafeNormalize(CameraWorldPosition.xyz - Position.xyz), | |
| ParticleDirection = SafeNormalize(Position.xyz - OldPosition.xyz); | |
| float4 Right_Square = CameraRight, | |
| Up_Square = CameraUp; | |
| float4 Right_Rotated = (-1.0 * cos(Input.Rotation) * Up_Square) + (sin(Input.Rotation) * Right_Square), | |
| Up_Rotated = ( sin(Input.Rotation) * Up_Square) + (cos(Input.Rotation) * Right_Square); | |
| float4 Right_Velocity = float4(SafeNormalize(cross(CameraDirection, ParticleDirection )), 0.0), | |
| Up_Velocity = float4(-ParticleDirection, 0.0); | |
| // The index stored in the x component of AxisRotationVectorIndices indicates the 'source'. | |
| // Calculate the new axis by crossing this with the CameraDirection | |
| float4 AxisRotationResultVectors[2]; | |
| int ARVIndex = AxisRotationVectorSourceIndex; | |
| float4 AxisSource = AxisRotationVectors[ARVIndex]; | |
| float4 Axis_Calculation = float4(SafeNormalize(cross(CameraDirection, AxisSource.xyz)), 0.0) * AxisSource.w; | |
| // The w component of the rotation vector should 'clear' any negation that was performed. | |
| AxisRotationResultVectors[0] = (ARVIndex != 0) ? Axis_Calculation : AxisSource; | |
| AxisRotationResultVectors[1] = (ARVIndex == 0) ? Axis_Calculation : AxisSource; | |
| // Clear the w component of the result | |
| AxisRotationResultVectors[0].w = 0.0f; | |
| AxisRotationResultVectors[1].w = 0.0f; | |
| Right = (Right_Rotated * ParticleUpRightResultScalars.x) + | |
| (Right_Velocity * ParticleUpRightResultScalars.y) + | |
| (AxisRotationResultVectors[0] * ParticleUpRightResultScalars.z); | |
| Up = (Up_Rotated * ParticleUpRightResultScalars.x) + | |
| (Up_Velocity * ParticleUpRightResultScalars.y) + | |
| (AxisRotationResultVectors[1] * ParticleUpRightResultScalars.z); | |
| /*** | |
| // enum EParticleScreenAlignment | |
| // { | |
| // PSA_Square, | |
| // PSA_Rectangle, | |
| // PSA_Velocity | |
| // }; | |
| Right = ScreenAlignment.x > 1.5f ? Right_Velocity : Right_Rotated; | |
| Up = ScreenAlignment.x > 1.5f ? Up_Velocity : Up_Rotated; | |
| ***/ | |
| } | |
| float4 CalcWorldPosition(FVertexFactoryInput Input) | |
| { | |
| float4 WorldPosition = MulMatrix(LocalToWorld,Input.Position); | |
| float4 Right, | |
| Up; | |
| GetTangents(Input,Right,Up); | |
| #if SUBUV_PARTICLES | |
| WorldPosition += Input.Size.x * (Input.Interp_Sizer.z - 0.5) * Right; | |
| WorldPosition += Input.Size.y * (Input.Interp_Sizer.w - 0.5) * Up; | |
| #else //#if SUBUV_PARTICLES | |
| WorldPosition += Input.Size.x * (Input.TexCoord.x - 0.5) * Right; | |
| WorldPosition += Input.Size.y * (Input.TexCoord.y - 0.5) * Up; | |
| #endif //#if SUBUV_PARTICLES | |
| return WorldPosition; | |
| } | |
| /** 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)) | |
| ); | |
| } | |
| float4 VertexFactoryGetWorldPosition(FVertexFactoryInput Input) | |
| { | |
| return CalcWorldPosition(Input); | |
| } | |
| FVertexFactoryInterpolants VertexFactoryGetInterpolants(FVertexFactoryInput Input) | |
| { | |
| FVertexFactoryInterpolants Interpolants; | |
| Interpolants.TexCoord = Input.TexCoord; | |
| Interpolants.Color = Input.Color; | |
| #if SUBUV_PARTICLES | |
| Interpolants.TexCoord1 = Input.TexCoord1; | |
| Interpolants.Interp_Sizer = Input.Interp_Sizer; | |
| #endif //SUBUV_PARTICLES | |
| #if WORLD_COORDS | |
| float3x3 TangentBasis = CalcTangentBasis(Input); | |
| Interpolants.TangentBasisNormal = float4(TangentBasis[2],determinant(TangentBasis)) * 0.5 + 0.5; | |
| Interpolants.TangentBasisTangent = TangentBasis[0] * 0.5 + 0.5; | |
| #endif | |
| return Interpolants; | |
| } | |
| float4 VertexFactoryGetPreviousWorldPosition(FVertexFactoryInput Input) | |
| { | |
| return VertexFactoryGetWorldPosition(Input); | |
| } | |
| /** | |
| * Get the 3x3 tangent basis vectors for this vertex factory | |
| * | |
| * @param Input - vertex input stream structure | |
| * @return 3x3 matrix | |
| */ | |
| float3x3 VertexFactoryGetTangentBasis( FVertexFactoryInput Input ) | |
| { | |
| return CalcTangentBasis(Input); | |
| } | |
| /** | |
| * Transform a vector from world space to tangent space | |
| * | |
| * @param Input - vertex input stream structure | |
| * @param TangentBasis - 3x3 matrix to transform to tangent space | |
| * @param WorldVector - vector in world space to transform | |
| * @return vector in tangent space | |
| */ | |
| float3 VertexFactoryWorldToTangentSpace( FVertexFactoryInput Input, float3x3 TangentBasis, float3 WorldVector ) | |
| { | |
| // we use a straight mul here because we are generating the matrix, so we don't worry about column major vs row major (which is what MulMatrix manages per-platform) | |
| return mul( | |
| TangentBasis, | |
| WorldVector | |
| ); | |
| } | |
| half3 VertexFactoryGetWorldNormal(FVertexFactoryInput Input) | |
| { | |
| float3x3 TangentBasis = VertexFactoryGetTangentBasis(Input); | |
| return TangentBasis[2]; | |
| } |
Xet Storage Details
- Size:
- 8.68 kB
- Xet hash:
- c07d9dd3a66358a544cd549dd35ff52ca9a5233e6bececa632eb66664b883766
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.