// Copyright Epic Games, Inc. All Rights Reserved. /*============================================================================= LocalVertexFactoryCommon.usf: Local vertex factory common functionality =============================================================================*/ #define NEEDS_PER_INSTANCE_PARAMS ((USE_INSTANCING || USE_INSTANCE_CULLING) && (USES_PER_INSTANCE_FADE_AMOUNT || USES_SPEEDTREE || USE_DITHERED_LOD_TRANSITION || (!VF_USE_PRIMITIVE_SCENE_DATA && USES_PER_INSTANCE_CUSTOM_DATA))) struct FVertexFactoryInterpolantsVSToPS { TANGENTTOWORLD_INTERPOLATOR_BLOCK #if INTERPOLATE_VERTEX_COLOR half4 Color : COLOR0; #endif #if NEEDS_PER_INSTANCE_PARAMS // x = per-instance fade out amount, y = hide/show flag, z dither fade cutoff, w - CustomData index nointerpolation float4 PerInstanceParams : COLOR1; #endif #if NUM_TEX_COORD_INTERPOLATORS float4 TexCoords[(NUM_TEX_COORD_INTERPOLATORS+1)/2] : TEXCOORD0; #elif USE_PARTICLE_SUBUVS float4 TexCoords[1] : TEXCOORD0; #endif #if NEEDS_LIGHTMAP_COORDINATE float4 LightMapCoordinate : TEXCOORD4; #endif #if VF_USE_PRIMITIVE_SCENE_DATA nointerpolation uint PrimitiveId : PRIMITIVE_ID; #if NEEDS_LIGHTMAP_COORDINATE nointerpolation uint LightmapDataIndex : LIGHTMAP_ID; #endif #if USES_PER_INSTANCE_CUSTOM_DATA nointerpolation uint CustomDataOffset : CUSTOM_DATA_OFFSET; nointerpolation uint CustomDataCount : CUSTOM_DATA_COUNT; #endif #endif #if NEEDS_PER_INSTANCE_RANDOM_PS nointerpolation float PerInstanceRandom : PER_INSTANCE_RANDOM; #endif #if HAIR_STRAND_MESH_FACTORY nointerpolation uint HairControlPointId : HAIR_PRIMITIVE_ID; // Control point ID float2 HairPrimitiveUV : HAIR_PRIMITIVE_UV; // U: parameteric distance between the two surrounding control points. V: parametric distance along the width. #endif #if HAIR_CARD_MESH_FACTORY float2 HairPrimitiveUV : HAIR_PRIMITIVE_UV; // Atlas UV float2 HairPrimitiveRootUV : HAIR_PRIMITIVE_ROOTUV;// UV at the root point of the cards float4 HairPrimitiveMaterial : HAIR_PRIMITIVE_MATERIAL; float HairPrimitiveLength : HAIR_PRIMITIVE_LENGTH; nointerpolation float HairPrimitiveGroupIndex : HAIR_PRIMITIVE_GROUPINDEX; #endif #if HAS_INSTANCE_LOCAL_TO_WORLD_PS nointerpolation float3x4 InstanceLocalToWorld : INSTANCE_LOCAL_TO_WORLD; #endif #if HAS_INSTANCE_WORLD_TO_LOCAL_PS nointerpolation float3x4 InstanceWorldToLocal : INSTANCE_WORLD_TO_LOCAL; #endif }; #if NUM_TEX_COORD_INTERPOLATORS || USE_PARTICLE_SUBUVS 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 float4 GetColor(FVertexFactoryInterpolantsVSToPS Interpolants) { #if INTERPOLATE_VERTEX_COLOR return Interpolants.Color; #else return 0; #endif } void SetColor(inout FVertexFactoryInterpolantsVSToPS Interpolants, float4 InValue) { #if INTERPOLATE_VERTEX_COLOR Interpolants.Color = InValue; #endif } #if NEEDS_LIGHTMAP_COORDINATE void GetLightMapCoordinates(FVertexFactoryInterpolantsVSToPS Interpolants, out float2 LightmapUV0, out float2 LightmapUV1, out uint LightmapDataIndex) { LightmapUV0 = Interpolants.LightMapCoordinate.xy * float2( 1, 0.5 ); LightmapUV1 = LightmapUV0 + float2( 0, 0.5 ); #if VF_USE_PRIMITIVE_SCENE_DATA && NEEDS_LIGHTMAP_COORDINATE LightmapDataIndex = Interpolants.LightmapDataIndex; #else LightmapDataIndex = 0; #endif } void GetShadowMapCoordinate(FVertexFactoryInterpolantsVSToPS Interpolants, out float2 ShadowMapCoordinate, out uint LightmapDataIndex) { #if VF_USE_PRIMITIVE_SCENE_DATA && NEEDS_LIGHTMAP_COORDINATE LightmapDataIndex = Interpolants.LightmapDataIndex; #else LightmapDataIndex = 0; #endif ShadowMapCoordinate = Interpolants.LightMapCoordinate.zw; } void SetLightMapCoordinate(inout FVertexFactoryInterpolantsVSToPS Interpolants, float2 InLightMapCoordinate, float2 InShadowMapCoordinate) { Interpolants.LightMapCoordinate.xy = InLightMapCoordinate; Interpolants.LightMapCoordinate.zw = InShadowMapCoordinate; } #endif float4 GetTangentToWorld2(FVertexFactoryInterpolantsVSToPS Interpolants) { return Interpolants.TangentToWorld2; } float4 GetTangentToWorld0(FVertexFactoryInterpolantsVSToPS Interpolants) { return Interpolants.TangentToWorld0; } void SetTangents(inout FVertexFactoryInterpolantsVSToPS Interpolants, float3 InTangentToWorld0, float3 InTangentToWorld2, float InTangentToWorldSign) { Interpolants.TangentToWorld0 = float4(InTangentToWorld0,0); Interpolants.TangentToWorld2 = float4(InTangentToWorld2,InTangentToWorldSign); #if USE_WORLDVERTEXNORMAL_CENTER_INTERPOLATION Interpolants.TangentToWorld2_Center = Interpolants.TangentToWorld2; #endif } uint GetPrimitiveId(FVertexFactoryInterpolantsVSToPS Interpolants) { #if VF_USE_PRIMITIVE_SCENE_DATA return Interpolants.PrimitiveId; #else return 0; #endif } void SetPrimitiveId(inout FVertexFactoryInterpolantsVSToPS Interpolants, uint PrimitiveId) { #if VF_USE_PRIMITIVE_SCENE_DATA Interpolants.PrimitiveId = PrimitiveId; #endif } void SetLightmapDataIndex(inout FVertexFactoryInterpolantsVSToPS Interpolants, uint LightmapDataIndex) { #if VF_USE_PRIMITIVE_SCENE_DATA && NEEDS_LIGHTMAP_COORDINATE Interpolants.LightmapDataIndex = LightmapDataIndex; #endif } #if HAS_INSTANCE_LOCAL_TO_WORLD_PS void SetInstanceLocalToWorld(inout FVertexFactoryInterpolantsVSToPS Interpolants, FDFMatrix InstanceLocalToWorld) { float4x4 InstanceLocalToTranslatedWorld = DFFastToTranslatedWorld(InstanceLocalToWorld, ResolvedView.PrevPreViewTranslation); float4x4 InstanceLocalToTranslatedWorldT = transpose(InstanceLocalToTranslatedWorld); Interpolants.InstanceLocalToWorld[0] = InstanceLocalToTranslatedWorldT[0]; Interpolants.InstanceLocalToWorld[1] = InstanceLocalToTranslatedWorldT[1]; Interpolants.InstanceLocalToWorld[2] = InstanceLocalToTranslatedWorldT[2]; } FDFMatrix GetInstanceLocalToWorld(FVertexFactoryInterpolantsVSToPS Interpolants) { float4x4 InstanceLocalToTranslatedWorld = transpose(float4x4(Interpolants.InstanceLocalToWorld[0], Interpolants.InstanceLocalToWorld[1], Interpolants.InstanceLocalToWorld[2], float4(0.0f, 0.0f, 0.0f, 1.0f))); return DFMultiplyTranslation(InstanceLocalToTranslatedWorld, DFNegate(ResolvedView.PrevPreViewTranslation)); } #endif #if HAS_INSTANCE_WORLD_TO_LOCAL_PS void SetInstanceWorldToLocal(inout FVertexFactoryInterpolantsVSToPS Interpolants, FDFInverseMatrix InstanceWorldToLocal) { float4x4 InstanceTranslatedWorldToLocal = DFFastToTranslatedWorld(InstanceWorldToLocal, ResolvedView.PrevPreViewTranslation); float4x4 InstanceTranslatedWorldToLocalT = transpose(InstanceTranslatedWorldToLocal); Interpolants.InstanceWorldToLocal[0] = InstanceTranslatedWorldToLocalT[0]; Interpolants.InstanceWorldToLocal[1] = InstanceTranslatedWorldToLocalT[1]; Interpolants.InstanceWorldToLocal[2] = InstanceTranslatedWorldToLocalT[2]; } FDFInverseMatrix GetInstanceWorldToLocal(FVertexFactoryInterpolantsVSToPS Interpolants) { float4x4 InstanceTranslatedWorldToLocal = transpose(float4x4(Interpolants.InstanceWorldToLocal[0], Interpolants.InstanceWorldToLocal[1], Interpolants.InstanceWorldToLocal[2], float4(0.0f, 0.0f, 0.0f, 1.0f))); return DFMultiplyTranslation(ResolvedView.PrevPreViewTranslation, InstanceTranslatedWorldToLocal); } #endif