// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. /*============================================================================= LocalVertexFactoryCommon.usf: Local vertex factory common functionality =============================================================================*/ // FVertexFactoryInterpolantsVSToPS is split into a PC and ES2 version, since the ES2 version has more restrictions on packing // Then accessors are provided for each property which try to encapsulate the packing differences #if FEATURE_LEVEL >= FEATURE_LEVEL_SM3 struct FVertexFactoryInterpolantsVSToPS { TANGENTTOWORLD_INTERPOLATOR_BLOCK #if INTERPOLATE_VERTEX_COLOR half4 Color : COLOR0; #endif #if USE_INSTANCING // x = per-instance random, y = per-instance fade out amount, z = hide/show flag float3 PerInstanceParams : COLOR1; #endif #if NUM_MATERIAL_TEXCOORDS float4 TexCoords[(NUM_MATERIAL_TEXCOORDS+1)/2] : TEXCOORD0; #elif USE_PARTICLE_SUBUVS float4 TexCoords[1] : TEXCOORD0; #endif #if NEEDS_LIGHTMAP_COORDINATE float4 LightMapCoordinate : TEXCOORD4; #endif }; #if NUM_MATERIAL_TEXCOORDS || 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) { LightmapUV0 = Interpolants.LightMapCoordinate.xy * float2( 1, 0.5 ); LightmapUV1 = LightmapUV0 + float2( 0, 0.5 ); } float2 GetShadowMapCoordinate(FVertexFactoryInterpolantsVSToPS Interpolants) { return Interpolants.LightMapCoordinate.zw; } void SetLightMapCoordinate(inout FVertexFactoryInterpolantsVSToPS Interpolants, float4 InLightMapCoordinate, float2 InShadowMapCoordinate) { Interpolants.LightMapCoordinate.xy = InLightMapCoordinate.xy; 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); } #else // #if FEATURE_LEVEL >= FEATURE_LEVEL_SM3 #define NUM_PACKED_UVS (NUM_MATERIAL_TEXCOORDS > 1 ? 3 : 1) #define USE_INTERPOLATOR_345 ((!MATERIAL_SHADINGMODEL_UNLIT) || USES_TRANSFORM_VECTOR || USES_DISTORTION) /** Interpolants packed for ES2. All UVs are in the xy to ensure independent texture fetches. */ struct FVertexFactoryInterpolantsVSToPS { // Save one interpolator if the material is only using one UV #if NUM_PACKED_UVS == 1 // UV0, normal xy float4 PackedUVs[1] : TEXCOORD0; #if INTERPOLATE_VERTEX_COLOR // Only interpolate vertex color if needed by the material pixel shader float4 Color : TEXCOORD1; #endif #else // UV0, normal xy // UV1, color xy // UV2, color zw float4 PackedUVs[3] : TEXCOORD0; #endif #if USE_INTERPOLATOR_345 // LightmapUV0, normal zw float4 PackedInterpolator3 : TEXCOORD3; // LightmapUV1, tangent xy float4 PackedInterpolator4 : TEXCOORD4; // ShadowmapUV, tangent zw float4 PackedInterpolator5 : TEXCOORD5; #endif #if USE_INSTANCING // x = per-instance random, y = per-instance fade out amount float3 PerInstanceParams : COLOR1; #endif }; float2 GetUV(FVertexFactoryInterpolantsVSToPS Interpolants, int UVIndex) { return Interpolants.PackedUVs[UVIndex].xy; } void SetUV(inout FVertexFactoryInterpolantsVSToPS Interpolants, int UVIndex, float2 InValue) { Interpolants.PackedUVs[UVIndex].xy = InValue; } float4 GetColor(FVertexFactoryInterpolantsVSToPS Interpolants) { #if NUM_PACKED_UVS == 1 #if INTERPOLATE_VERTEX_COLOR return Interpolants.Color; #else return 0; #endif #else return float4(Interpolants.PackedUVs[1].zw, Interpolants.PackedUVs[2].zw); #endif } void SetColor(inout FVertexFactoryInterpolantsVSToPS Interpolants, float4 InValue) { #if NUM_PACKED_UVS == 1 #if INTERPOLATE_VERTEX_COLOR Interpolants.Color = InValue; #endif #else Interpolants.PackedUVs[1].zw = InValue.xy; Interpolants.PackedUVs[2].zw = InValue.zw; #endif } void GetLightMapCoordinates(FVertexFactoryInterpolantsVSToPS Interpolants, out float2 LightmapUV0, out float2 LightmapUV1) { #if USE_INTERPOLATOR_345 LightmapUV0 = Interpolants.PackedInterpolator3.xy; LightmapUV1 = Interpolants.PackedInterpolator4.xy; #else LightmapUV0 = LightmapUV1 = 0; #endif } float2 GetShadowMapCoordinate(FVertexFactoryInterpolantsVSToPS Interpolants) { #if USE_INTERPOLATOR_345 return Interpolants.PackedInterpolator5.xy; #else return float2(0, 0); #endif } void SetLightMapCoordinate(inout FVertexFactoryInterpolantsVSToPS Interpolants, float4 InLightMapCoordinate, float2 InShadowMapCoordinate) { #if USE_INTERPOLATOR_345 Interpolants.PackedInterpolator3.xy = InLightMapCoordinate.xy; Interpolants.PackedInterpolator4.xy = InLightMapCoordinate.zw; Interpolants.PackedInterpolator5.xy = InShadowMapCoordinate; #endif } float4 GetTangentToWorld2(FVertexFactoryInterpolantsVSToPS Interpolants) { #if USE_INTERPOLATOR_345 return float4(Interpolants.PackedUVs[0].zw, Interpolants.PackedInterpolator3.zw); #else return float4(0, 0, 0, 1); #endif } float4 GetTangentToWorld0(FVertexFactoryInterpolantsVSToPS Interpolants) { #if USE_INTERPOLATOR_345 return float4(Interpolants.PackedInterpolator4.zw, Interpolants.PackedInterpolator5.zw); #else return float4(0, 0, 0, 0); #endif } void SetTangents(inout FVertexFactoryInterpolantsVSToPS Interpolants, float3 InTangentToWorld0, float3 InTangentToWorld2, float InTangentToWorldSign) { #if USE_INTERPOLATOR_345 Interpolants.PackedInterpolator4.zw = InTangentToWorld0.xy; Interpolants.PackedInterpolator5.zw = InTangentToWorld0.zz; Interpolants.PackedUVs[0].zw = InTangentToWorld2.xy; Interpolants.PackedInterpolator3.zw = float2(InTangentToWorld2.z,InTangentToWorldSign); #else Interpolants.PackedUVs[0].zw = 0; #endif } #endif