2019-01-03 19:16:26 -05:00
|
|
|
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
|
2017-07-26 10:00:02 -04:00
|
|
|
|
|
|
|
|
/*=============================================================================
|
|
|
|
|
LocalVertexFactory.usf: Local vertex factory shader code.
|
|
|
|
|
=============================================================================*/
|
|
|
|
|
|
|
|
|
|
#include "VertexFactoryCommon.ush"
|
|
|
|
|
#include "LocalVertexFactoryCommon.ush"
|
2018-12-11 22:25:04 -05:00
|
|
|
#include "LightmapData.ush"
|
2017-07-26 10:00:02 -04:00
|
|
|
|
|
|
|
|
#if GPUSKIN_PASS_THROUGH
|
|
|
|
|
#include "GpuSkinCommon.ush"
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#include "/Engine/Generated/UniformBuffers/PrecomputedLightingBuffer.ush"
|
|
|
|
|
|
|
|
|
|
#if USE_INSTANCING
|
|
|
|
|
#ifndef USE_DITHERED_LOD_TRANSITION_FOR_INSTANCED
|
|
|
|
|
#error "USE_DITHERED_LOD_TRANSITION_FOR_INSTANCED should have been defined"
|
|
|
|
|
#endif
|
|
|
|
|
#define USE_DITHERED_LOD_TRANSITION USE_DITHERED_LOD_TRANSITION_FOR_INSTANCED
|
|
|
|
|
#else
|
|
|
|
|
#ifndef USE_DITHERED_LOD_TRANSITION_FROM_MATERIAL
|
|
|
|
|
#error "USE_DITHERED_LOD_TRANSITION_FROM_MATERIAL should have been defined"
|
|
|
|
|
#endif
|
|
|
|
|
#define USE_DITHERED_LOD_TRANSITION USE_DITHERED_LOD_TRANSITION_FROM_MATERIAL
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if USE_INSTANCING
|
|
|
|
|
|
|
|
|
|
#if USE_DITHERED_LOD_TRANSITION
|
|
|
|
|
float4 InstancingViewZCompareZero; // w contains random lod scale
|
|
|
|
|
float4 InstancingViewZCompareOne;
|
|
|
|
|
float4 InstancingViewZConstant;
|
|
|
|
|
float4 InstancingWorldViewOriginZero;
|
|
|
|
|
float4 InstancingWorldViewOriginOne;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
float4 InstancingFadeOutParams;
|
|
|
|
|
|
|
|
|
|
#ifndef USE_INSTANCING_EMULATED
|
|
|
|
|
#define USE_INSTANCING_EMULATED 0
|
|
|
|
|
#endif // USE_INSTANCING_EMULATED
|
|
|
|
|
|
|
|
|
|
#if USE_INSTANCING_EMULATED
|
|
|
|
|
// Required for CPU emulation of Instancing
|
|
|
|
|
float4 CPUInstanceOrigin; // per-instance random in w
|
|
|
|
|
float3x4 CPUInstanceTransform; // hitproxy.r + 256 * selected in .w; hitproxy.g in .w; hitproxy.b in .w
|
|
|
|
|
float4 CPUInstanceLightmapAndShadowMapBias;
|
|
|
|
|
#endif // USE_INSTANCING_EMULATED
|
|
|
|
|
|
|
|
|
|
#else // USE_INSTANCING
|
|
|
|
|
#ifndef USE_INSTANCING_EMULATED
|
|
|
|
|
#define USE_INSTANCING_EMULATED (0)
|
|
|
|
|
#endif
|
|
|
|
|
#endif // USE_INSTANCING
|
|
|
|
|
|
|
|
|
|
#if USE_SPLINEDEFORM
|
2018-12-14 11:54:34 -05:00
|
|
|
float3 SplineStartPos;
|
|
|
|
|
float3 SplineStartTangent;
|
2017-07-26 10:00:02 -04:00
|
|
|
float SplineStartRoll;
|
|
|
|
|
float2 SplineStartScale;
|
|
|
|
|
float2 SplineStartOffset;
|
|
|
|
|
|
2018-12-14 11:54:34 -05:00
|
|
|
float3 SplineEndPos;
|
|
|
|
|
float3 SplineEndTangent;
|
2017-07-26 10:00:02 -04:00
|
|
|
float SplineEndRoll;
|
|
|
|
|
float2 SplineEndScale;
|
|
|
|
|
float2 SplineEndOffset;
|
|
|
|
|
|
2018-12-14 11:54:34 -05:00
|
|
|
float3 SplineUpDir;
|
2017-07-26 10:00:02 -04:00
|
|
|
#if ES2_PROFILE
|
|
|
|
|
float SmoothInterpRollScale;
|
|
|
|
|
#else
|
|
|
|
|
bool SmoothInterpRollScale;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
float SplineMeshMinZ;
|
|
|
|
|
float SplineMeshScaleZ;
|
|
|
|
|
|
2018-12-14 11:54:34 -05:00
|
|
|
float3 SplineMeshDir;
|
|
|
|
|
float3 SplineMeshX;
|
|
|
|
|
float3 SplineMeshY;
|
2017-07-26 10:00:02 -04:00
|
|
|
#endif // USE_SPLINEDEFORM
|
|
|
|
|
|
2017-10-13 11:32:28 -04:00
|
|
|
#ifndef MANUAL_VERTEX_FETCH
|
|
|
|
|
#define MANUAL_VERTEX_FETCH 0
|
|
|
|
|
#endif
|
|
|
|
|
|
2018-12-18 21:41:17 -05:00
|
|
|
|
2017-10-13 11:32:28 -04:00
|
|
|
|
|
|
|
|
#if MANUAL_VERTEX_FETCH
|
|
|
|
|
Buffer<float4> VertexFetch_InstanceOriginBuffer;
|
|
|
|
|
Buffer<float4> VertexFetch_InstanceTransformBuffer;
|
|
|
|
|
Buffer<float4> VertexFetch_InstanceLightmapBuffer;
|
|
|
|
|
|
2019-06-08 17:15:34 -04:00
|
|
|
#if USE_INSTANCING && USE_INSTANCING_BONEMAP
|
|
|
|
|
Buffer<float4> VertexFetch_InstancePrevTransformBuffer;
|
|
|
|
|
Buffer<uint> VertexFetch_InstanceBoneMapBuffer;
|
|
|
|
|
#endif
|
|
|
|
|
|
2018-12-11 22:25:04 -05:00
|
|
|
uint InstanceOffset;
|
2017-10-13 11:32:28 -04:00
|
|
|
|
|
|
|
|
#define VF_ColorIndexMask_Index 0
|
|
|
|
|
#define VF_NumTexcoords_Index 1
|
|
|
|
|
#define FV_LightMapIndex_Index 2
|
2018-12-11 22:25:04 -05:00
|
|
|
#define VF_VertexOffset 3
|
2017-10-13 11:32:28 -04:00
|
|
|
#endif
|
|
|
|
|
|
2018-12-11 22:25:04 -05:00
|
|
|
/**
|
|
|
|
|
* Per-vertex inputs from bound vertex buffers
|
|
|
|
|
*/
|
2017-07-26 10:00:02 -04:00
|
|
|
struct FVertexFactoryInput
|
|
|
|
|
{
|
|
|
|
|
float4 Position : ATTRIBUTE0;
|
2017-10-13 11:32:28 -04:00
|
|
|
|
|
|
|
|
#if !MANUAL_VERTEX_FETCH
|
|
|
|
|
#if METAL_PROFILE
|
|
|
|
|
float3 TangentX : ATTRIBUTE1;
|
|
|
|
|
// TangentZ.w contains sign of tangent basis determinant
|
|
|
|
|
float4 TangentZ : ATTRIBUTE2;
|
|
|
|
|
|
|
|
|
|
float4 Color : ATTRIBUTE3;
|
|
|
|
|
#else
|
|
|
|
|
half3 TangentX : ATTRIBUTE1;
|
|
|
|
|
// TangentZ.w contains sign of tangent basis determinant
|
|
|
|
|
half4 TangentZ : ATTRIBUTE2;
|
|
|
|
|
|
|
|
|
|
half4 Color : ATTRIBUTE3;
|
|
|
|
|
#endif
|
|
|
|
|
#endif
|
2017-07-26 10:00:02 -04:00
|
|
|
|
|
|
|
|
#if NUM_MATERIAL_TEXCOORDS_VERTEX
|
2017-10-13 11:32:28 -04:00
|
|
|
#if !MANUAL_VERTEX_FETCH
|
|
|
|
|
#if GPUSKIN_PASS_THROUGH
|
|
|
|
|
// These must match GPUSkinVertexFactory.usf
|
|
|
|
|
float2 TexCoords[NUM_MATERIAL_TEXCOORDS_VERTEX] : ATTRIBUTE4;
|
|
|
|
|
#if NUM_MATERIAL_TEXCOORDS_VERTEX > 4
|
|
|
|
|
#error Too many texture coordinate sets defined on GPUSkin vertex input. Max: 4.
|
|
|
|
|
#endif
|
|
|
|
|
#else
|
|
|
|
|
#if NUM_MATERIAL_TEXCOORDS_VERTEX > 1
|
|
|
|
|
float4 PackedTexCoords4[NUM_MATERIAL_TEXCOORDS_VERTEX/2] : ATTRIBUTE4;
|
|
|
|
|
#endif
|
|
|
|
|
#if NUM_MATERIAL_TEXCOORDS_VERTEX == 1
|
|
|
|
|
float2 PackedTexCoords2 : ATTRIBUTE4;
|
|
|
|
|
#elif NUM_MATERIAL_TEXCOORDS_VERTEX == 3
|
|
|
|
|
float2 PackedTexCoords2 : ATTRIBUTE5;
|
|
|
|
|
#elif NUM_MATERIAL_TEXCOORDS_VERTEX == 5
|
|
|
|
|
float2 PackedTexCoords2 : ATTRIBUTE6;
|
|
|
|
|
#elif NUM_MATERIAL_TEXCOORDS_VERTEX == 7
|
|
|
|
|
float2 PackedTexCoords2 : ATTRIBUTE7;
|
|
|
|
|
#endif
|
2017-07-26 10:00:02 -04:00
|
|
|
#endif
|
|
|
|
|
#endif
|
2017-10-13 11:32:28 -04:00
|
|
|
#elif USE_PARTICLE_SUBUVS && !MANUAL_VERTEX_FETCH
|
2017-07-26 10:00:02 -04:00
|
|
|
float2 TexCoords[1] : ATTRIBUTE4;
|
|
|
|
|
#endif
|
|
|
|
|
|
2017-10-13 11:32:28 -04:00
|
|
|
#if USE_INSTANCING && !USE_INSTANCING_EMULATED && !MANUAL_VERTEX_FETCH
|
2017-07-26 10:00:02 -04:00
|
|
|
float4 InstanceOrigin : ATTRIBUTE8; // per-instance random in w
|
|
|
|
|
half4 InstanceTransform1 : ATTRIBUTE9; // hitproxy.r + 256 * selected in .w
|
|
|
|
|
half4 InstanceTransform2 : ATTRIBUTE10; // hitproxy.g in .w
|
|
|
|
|
half4 InstanceTransform3 : ATTRIBUTE11; // hitproxy.b in .w
|
|
|
|
|
float4 InstanceLightmapAndShadowMapUVBias : ATTRIBUTE12;
|
|
|
|
|
#endif //USE_INSTANCING && !USE_INSTANCING_EMULATED
|
|
|
|
|
|
2018-12-11 22:25:04 -05:00
|
|
|
#if VF_USE_PRIMITIVE_SCENE_DATA
|
|
|
|
|
uint PrimitiveId : ATTRIBUTE13;
|
|
|
|
|
#endif
|
|
|
|
|
|
2017-10-13 11:32:28 -04:00
|
|
|
#if NEEDS_LIGHTMAP_COORDINATE && !MANUAL_VERTEX_FETCH
|
2017-07-26 10:00:02 -04:00
|
|
|
float2 LightMapCoordinate : ATTRIBUTE15;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/** Optional instance ID for vertex layered rendering */
|
2018-12-11 22:25:04 -05:00
|
|
|
#if FEATURE_LEVEL >= FEATURE_LEVEL_ES3_1 && (MANUAL_VERTEX_FETCH && (USE_INSTANCING && !USE_INSTANCING_EMULATED))
|
2017-07-26 10:00:02 -04:00
|
|
|
uint InstanceId : SV_InstanceID;
|
|
|
|
|
#endif
|
|
|
|
|
|
2017-10-13 11:32:28 -04:00
|
|
|
#if GPUSKIN_PASS_THROUGH || MANUAL_VERTEX_FETCH
|
2017-07-26 10:00:02 -04:00
|
|
|
uint VertexId : SV_VertexID;
|
|
|
|
|
#endif
|
|
|
|
|
};
|
|
|
|
|
|
2018-12-18 21:41:17 -05:00
|
|
|
#if RAYHITGROUPSHADER
|
|
|
|
|
FVertexFactoryInput LoadVertexFactoryInput(uint TriangleIndex, int VertexIndex)
|
|
|
|
|
{
|
|
|
|
|
FTriangleBaseAttributes Triangle = LoadTriangleBaseAttributes(TriangleIndex);
|
|
|
|
|
|
|
|
|
|
FVertexFactoryInput Input;
|
2019-01-24 17:53:53 -05:00
|
|
|
Input.Position = float4(Triangle.LocalPositions[VertexIndex], 1.0f);
|
2018-12-18 21:41:17 -05:00
|
|
|
Input.VertexId = Triangle.Indices[VertexIndex];
|
|
|
|
|
#if VF_USE_PRIMITIVE_SCENE_DATA
|
|
|
|
|
Input.PrimitiveId = GetInstanceUserData();
|
|
|
|
|
#endif
|
|
|
|
|
return Input;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2018-12-11 22:25:04 -05:00
|
|
|
/**
|
|
|
|
|
* Per-vertex inputs from bound vertex buffers. Used by passes with a trimmed down position-only shader.
|
|
|
|
|
*/
|
2017-07-26 10:00:02 -04:00
|
|
|
struct FPositionOnlyVertexFactoryInput
|
|
|
|
|
{
|
|
|
|
|
float4 Position : ATTRIBUTE0;
|
2017-10-13 11:32:28 -04:00
|
|
|
|
|
|
|
|
#if USE_INSTANCING && !USE_INSTANCING_EMULATED && !MANUAL_VERTEX_FETCH
|
2017-07-26 10:00:02 -04:00
|
|
|
float4 InstanceOrigin : ATTRIBUTE8; // per-instance random in w
|
|
|
|
|
half4 InstanceTransform1 : ATTRIBUTE9; // hitproxy.r + 256 * selected in .w
|
|
|
|
|
half4 InstanceTransform2 : ATTRIBUTE10; // hitproxy.g in .w
|
|
|
|
|
half4 InstanceTransform3 : ATTRIBUTE11; // hitproxy.b in .w
|
|
|
|
|
#endif // USE_INSTANCING && !USE_INSTANCING_EMULATED
|
|
|
|
|
|
2018-12-11 22:25:04 -05:00
|
|
|
#if VF_USE_PRIMITIVE_SCENE_DATA
|
|
|
|
|
uint PrimitiveId : ATTRIBUTE1;
|
|
|
|
|
#endif
|
|
|
|
|
|
2017-07-26 10:00:02 -04:00
|
|
|
/** Optional instance ID for vertex layered rendering */
|
2018-12-11 22:25:04 -05:00
|
|
|
#if (FEATURE_LEVEL >= FEATURE_LEVEL_ES3_1) && (MANUAL_VERTEX_FETCH && (USE_INSTANCING && !USE_INSTANCING_EMULATED))
|
2017-07-26 10:00:02 -04:00
|
|
|
uint InstanceId : SV_InstanceID;
|
|
|
|
|
#endif
|
2017-10-13 11:32:28 -04:00
|
|
|
|
|
|
|
|
#if MANUAL_VERTEX_FETCH
|
|
|
|
|
uint VertexId : SV_VertexID;
|
|
|
|
|
#endif
|
2017-07-26 10:00:02 -04:00
|
|
|
};
|
|
|
|
|
|
2018-12-11 22:25:04 -05:00
|
|
|
/**
|
|
|
|
|
* Caches intermediates that would otherwise have to be computed multiple times. Avoids relying on the compiler to optimize out redundant operations.
|
|
|
|
|
*/
|
2017-07-26 10:00:02 -04:00
|
|
|
struct FVertexFactoryIntermediates
|
|
|
|
|
{
|
|
|
|
|
half3x3 TangentToLocal;
|
|
|
|
|
half3x3 TangentToWorld;
|
|
|
|
|
half TangentToWorldSign;
|
|
|
|
|
|
|
|
|
|
half4 Color;
|
|
|
|
|
#if USE_INSTANCING
|
2017-10-13 11:32:28 -04:00
|
|
|
#if !USE_INSTANCING_EMULATED
|
|
|
|
|
float4 InstanceOrigin;
|
|
|
|
|
float4 InstanceTransform1;
|
|
|
|
|
float4 InstanceTransform2;
|
|
|
|
|
float4 InstanceTransform3;
|
2019-06-08 17:15:34 -04:00
|
|
|
|
|
|
|
|
#if USE_INSTANCING_BONEMAP
|
|
|
|
|
float4 InstancePrevOrigin;
|
|
|
|
|
float4 InstancePrevTransform1;
|
|
|
|
|
float4 InstancePrevTransform2;
|
|
|
|
|
float4 InstancePrevTransform3;
|
|
|
|
|
#endif
|
|
|
|
|
|
2017-10-13 11:32:28 -04:00
|
|
|
float4 InstanceLightmapAndShadowMapUVBias;
|
|
|
|
|
#endif
|
2017-07-26 10:00:02 -04:00
|
|
|
// x = per-instance random, y = per-instance fade out amount, z = hide/show flag, w dither fade cutoff
|
|
|
|
|
float4 PerInstanceParams;
|
|
|
|
|
#endif // USE_INSTANCING
|
2018-12-11 22:25:04 -05:00
|
|
|
uint PrimitiveId;
|
2017-07-26 10:00:02 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#if USE_INSTANCING
|
2017-10-13 11:32:28 -04:00
|
|
|
float4x4 GetInstanceTransform(FVertexFactoryIntermediates Intermediates)
|
2017-07-26 10:00:02 -04:00
|
|
|
{
|
|
|
|
|
#if !USE_INSTANCING_EMULATED
|
|
|
|
|
return float4x4(
|
2017-10-13 11:32:28 -04:00
|
|
|
float4(Intermediates.InstanceTransform1.xyz, 0.0f),
|
|
|
|
|
float4(Intermediates.InstanceTransform2.xyz, 0.0f),
|
|
|
|
|
float4(Intermediates.InstanceTransform3.xyz, 0.0f),
|
|
|
|
|
float4(Intermediates.InstanceOrigin.xyz, 1.0f));
|
2017-07-26 10:00:02 -04:00
|
|
|
#else
|
|
|
|
|
return float4x4(
|
|
|
|
|
float4(CPUInstanceTransform[0].xyz, 0.0f),
|
|
|
|
|
float4(CPUInstanceTransform[1].xyz, 0.0f),
|
|
|
|
|
float4(CPUInstanceTransform[2].xyz, 0.0f),
|
|
|
|
|
float4(CPUInstanceOrigin.xyz, 1.0f));
|
|
|
|
|
#endif // !USE_INSTANCING_EMULATED
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-08 17:15:34 -04:00
|
|
|
#if USE_INSTANCING && USE_INSTANCING_BONEMAP
|
|
|
|
|
float4x4 GetInstancePrevTransform(FVertexFactoryIntermediates Intermediates)
|
|
|
|
|
{
|
|
|
|
|
return float4x4(
|
|
|
|
|
float4(Intermediates.InstancePrevTransform1.xyz, 0.0f),
|
|
|
|
|
float4(Intermediates.InstancePrevTransform2.xyz, 0.0f),
|
|
|
|
|
float4(Intermediates.InstancePrevTransform3.xyz, 0.0f),
|
|
|
|
|
float4(Intermediates.InstancePrevOrigin.xyz, 1.0f));
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2017-07-26 10:00:02 -04:00
|
|
|
float4x4 GetInstanceTransform(FPositionOnlyVertexFactoryInput Input)
|
|
|
|
|
{
|
2019-06-08 17:15:34 -04:00
|
|
|
#if !USE_INSTANCING_EMULATED && MANUAL_VERTEX_FETCH && !USE_INSTANCING_BONEMAP
|
2019-01-17 05:02:52 -05:00
|
|
|
uint InstanceId = GetInstanceId(Input.InstanceId);
|
2017-07-26 10:00:02 -04:00
|
|
|
return float4x4(
|
2019-01-17 05:02:52 -05:00
|
|
|
float4(VertexFetch_InstanceTransformBuffer[3 * (InstanceId + InstanceOffset) + 0].xyz, 0.0f),
|
|
|
|
|
float4(VertexFetch_InstanceTransformBuffer[3 * (InstanceId + InstanceOffset) + 1].xyz, 0.0f),
|
|
|
|
|
float4(VertexFetch_InstanceTransformBuffer[3 * (InstanceId + InstanceOffset) + 2].xyz, 0.0f),
|
|
|
|
|
float4(VertexFetch_InstanceOriginBuffer[(InstanceId + InstanceOffset)].xyz, 1.0f));
|
2019-06-08 17:15:34 -04:00
|
|
|
#elif !USE_INSTANCING_EMULATED && MANUAL_VERTEX_FETCH && USE_INSTANCING_BONEMAP
|
|
|
|
|
uint InstanceIndex = VertexFetch_InstanceBoneMapBuffer[LocalVF.VertexFetch_Parameters[VF_VertexOffset] + Input.VertexId];
|
|
|
|
|
return float4x4(
|
|
|
|
|
float4(VertexFetch_InstanceTransformBuffer[4 * InstanceIndex + 0].xyz, 0.0f),
|
|
|
|
|
float4(VertexFetch_InstanceTransformBuffer[4 * InstanceIndex + 1].xyz, 0.0f),
|
|
|
|
|
float4(VertexFetch_InstanceTransformBuffer[4 * InstanceIndex + 2].xyz, 0.0f),
|
|
|
|
|
float4(VertexFetch_InstanceTransformBuffer[4 * InstanceIndex + 3].xyz, 1.0f));
|
2017-10-13 11:32:28 -04:00
|
|
|
#elif !USE_INSTANCING_EMULATED
|
|
|
|
|
return float4x4(
|
|
|
|
|
float4(Input.InstanceTransform1.xyz, 0.0f),
|
|
|
|
|
float4(Input.InstanceTransform2.xyz, 0.0f),
|
|
|
|
|
float4(Input.InstanceTransform3.xyz, 0.0f),
|
2017-07-26 10:00:02 -04:00
|
|
|
float4(Input.InstanceOrigin.xyz, 1.0f));
|
|
|
|
|
#else
|
|
|
|
|
return float4x4(
|
|
|
|
|
float4(CPUInstanceTransform[0].xyz, 0.0f),
|
|
|
|
|
float4(CPUInstanceTransform[1].xyz, 0.0f),
|
|
|
|
|
float4(CPUInstanceTransform[2].xyz, 0.0f),
|
|
|
|
|
float4(CPUInstanceOrigin.xyz, 1.0f));
|
|
|
|
|
#endif // !USE_INSTANCING_EMULATED
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-13 11:32:28 -04:00
|
|
|
half3x3 GetInstanceToLocal3x3(FVertexFactoryIntermediates Intermediates)
|
2017-07-26 10:00:02 -04:00
|
|
|
{
|
|
|
|
|
#if !USE_INSTANCING_EMULATED
|
2017-10-13 11:32:28 -04:00
|
|
|
return half3x3(Intermediates.InstanceTransform1.xyz, Intermediates.InstanceTransform2.xyz, Intermediates.InstanceTransform3.xyz);
|
2017-07-26 10:00:02 -04:00
|
|
|
#else
|
|
|
|
|
return half3x3(half3(CPUInstanceTransform[0].xyz), half3(CPUInstanceTransform[1].xyz), half3(CPUInstanceTransform[2].xyz));
|
|
|
|
|
#endif // !USE_INSTANCING_EMULATED
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-13 11:32:28 -04:00
|
|
|
float2 GetInstanceShadowMapBias(FVertexFactoryIntermediates Intermediates)
|
2017-07-26 10:00:02 -04:00
|
|
|
{
|
|
|
|
|
#if !USE_INSTANCING_EMULATED
|
2017-10-13 11:32:28 -04:00
|
|
|
return Intermediates.InstanceLightmapAndShadowMapUVBias.zw;
|
2017-07-26 10:00:02 -04:00
|
|
|
#else
|
|
|
|
|
return CPUInstanceLightmapAndShadowMapBias.zw;
|
|
|
|
|
#endif // !USE_INSTANCING_EMULATED
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-13 11:32:28 -04:00
|
|
|
float2 GetInstanceLightMapBias(FVertexFactoryIntermediates Intermediates)
|
2017-07-26 10:00:02 -04:00
|
|
|
{
|
|
|
|
|
#if !USE_INSTANCING_EMULATED
|
2017-10-13 11:32:28 -04:00
|
|
|
return Intermediates.InstanceLightmapAndShadowMapUVBias.xy;
|
2017-07-26 10:00:02 -04:00
|
|
|
#else
|
|
|
|
|
return CPUInstanceLightmapAndShadowMapBias.xy;
|
|
|
|
|
#endif // !USE_INSTANCING_EMULATED
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-13 11:32:28 -04:00
|
|
|
float GetInstanceSelected(FVertexFactoryIntermediates Intermediates)
|
2017-07-26 10:00:02 -04:00
|
|
|
{
|
|
|
|
|
#if !USE_INSTANCING_EMULATED
|
2017-10-13 11:32:28 -04:00
|
|
|
float SelectedValue = trunc(Intermediates.InstanceTransform1.w * (1.0 / 256.0));
|
2017-07-26 10:00:02 -04:00
|
|
|
#else
|
|
|
|
|
float SelectedValue = trunc(CPUInstanceTransform[0].w * (1.0 / 256.0));
|
|
|
|
|
#endif // !USE_INSTANCING_EMULATED
|
|
|
|
|
return SelectedValue;
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-13 11:32:28 -04:00
|
|
|
float GetInstanceRandom(FVertexFactoryIntermediates Intermediates)
|
2017-07-26 10:00:02 -04:00
|
|
|
{
|
|
|
|
|
#if !USE_INSTANCING_EMULATED
|
2017-10-13 11:32:28 -04:00
|
|
|
float RandomVal = Intermediates.InstanceOrigin.w;
|
2017-07-26 10:00:02 -04:00
|
|
|
#else
|
|
|
|
|
float RandomVal = CPUInstanceOrigin.w;
|
|
|
|
|
#endif // !USE_INSTANCING_EMULATED
|
|
|
|
|
return RandomVal;
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-13 11:32:28 -04:00
|
|
|
float3 GetInstanceOrigin(FVertexFactoryIntermediates Intermediates)
|
2017-07-26 10:00:02 -04:00
|
|
|
{
|
|
|
|
|
#if !USE_INSTANCING_EMULATED
|
2017-10-13 11:32:28 -04:00
|
|
|
float3 Origin = Intermediates.InstanceOrigin.xyz;
|
2017-07-26 10:00:02 -04:00
|
|
|
#else
|
|
|
|
|
float3 Origin = CPUInstanceOrigin.xyz;
|
|
|
|
|
#endif // !USE_INSTANCING_EMULATED
|
|
|
|
|
return Origin;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif // USE_INSTANCING
|
|
|
|
|
|
|
|
|
|
/** 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 CoordinateIndex = 0; CoordinateIndex < NUM_TEX_COORD_INTERPOLATORS; CoordinateIndex++ )
|
|
|
|
|
{
|
|
|
|
|
Result.TexCoords[CoordinateIndex] = GetUV(Interpolants, CoordinateIndex);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if USE_PARTICLE_SUBUVS
|
|
|
|
|
// Output TexCoord0 for when previewing materials that use ParticleSubUV.
|
|
|
|
|
Result.Particle.SubUVCoords[0] = GetUV(Interpolants, 0);
|
|
|
|
|
Result.Particle.SubUVCoords[1] = GetUV(Interpolants, 0);
|
|
|
|
|
#endif // USE_PARTICLE_SUBUVS
|
|
|
|
|
|
|
|
|
|
half3 TangentToWorld0 = GetTangentToWorld0(Interpolants).xyz;
|
|
|
|
|
half4 TangentToWorld2 = GetTangentToWorld2(Interpolants);
|
|
|
|
|
Result.UnMirrored = TangentToWorld2.w;
|
|
|
|
|
|
|
|
|
|
Result.VertexColor = GetColor(Interpolants);
|
|
|
|
|
|
|
|
|
|
// Required for previewing materials that use ParticleColor
|
|
|
|
|
Result.Particle.Color = half4(1,1,1,1);
|
|
|
|
|
#if USE_INSTANCING
|
|
|
|
|
Result.PerInstanceParams = Interpolants.PerInstanceParams;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
Result.TangentToWorld = AssembleTangentToWorld( TangentToWorld0, TangentToWorld2 );
|
2018-03-07 17:03:49 -05:00
|
|
|
#if USE_WORLDVERTEXNORMAL_CENTER_INTERPOLATION
|
|
|
|
|
Result.WorldVertexNormal_Center = Interpolants.TangentToWorld2_Center.xyz;
|
|
|
|
|
#endif
|
2017-07-26 10:00:02 -04:00
|
|
|
|
|
|
|
|
#if LIGHTMAP_UV_ACCESS
|
|
|
|
|
#if NEEDS_LIGHTMAP_COORDINATE
|
|
|
|
|
#if (ES2_PROFILE || ES3_1_PROFILE)
|
|
|
|
|
// Not supported in pixel shader
|
|
|
|
|
Result.LightmapUVs = float2(0, 0);
|
|
|
|
|
#else
|
|
|
|
|
Result.LightmapUVs = Interpolants.LightMapCoordinate.xy;
|
|
|
|
|
#endif // ES2_PROFILE
|
|
|
|
|
#endif // NEEDS_LIGHTMAP_COORDINATE
|
|
|
|
|
#endif // LIGHTMAP_UV_ACCESS
|
|
|
|
|
|
|
|
|
|
Result.TwoSidedSign = 1;
|
2018-12-11 22:25:04 -05:00
|
|
|
Result.PrimitiveId = GetPrimitiveId(Interpolants);
|
|
|
|
|
|
2017-07-26 10:00:02 -04:00
|
|
|
return Result;
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-11 22:25:04 -05:00
|
|
|
half3x3 CalcTangentToWorldNoScale(FVertexFactoryIntermediates Intermediates, half3x3 TangentToLocal)
|
2017-07-26 10:00:02 -04:00
|
|
|
{
|
2018-12-11 22:25:04 -05:00
|
|
|
half3x3 LocalToWorld = GetLocalToWorld3x3(Intermediates.PrimitiveId);
|
|
|
|
|
half3 InvScale = GetPrimitiveData(Intermediates.PrimitiveId).InvNonUniformScaleAndDeterminantSign.xyz;
|
2017-07-26 10:00:02 -04:00
|
|
|
LocalToWorld[0] *= InvScale.x;
|
|
|
|
|
LocalToWorld[1] *= InvScale.y;
|
|
|
|
|
LocalToWorld[2] *= InvScale.z;
|
|
|
|
|
return mul(TangentToLocal, LocalToWorld);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** 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, half3x3 TangentToLocal)
|
|
|
|
|
{
|
|
|
|
|
FMaterialVertexParameters Result = (FMaterialVertexParameters)0;
|
|
|
|
|
Result.WorldPosition = WorldPosition;
|
|
|
|
|
Result.VertexColor = Intermediates.Color;
|
|
|
|
|
|
|
|
|
|
// does not handle instancing!
|
|
|
|
|
Result.TangentToWorld = Intermediates.TangentToWorld;
|
|
|
|
|
|
|
|
|
|
#if USE_INSTANCING
|
2018-12-11 22:25:04 -05:00
|
|
|
Result.InstanceLocalToWorld = mul(GetInstanceTransform(Intermediates), GetPrimitiveData(Intermediates.PrimitiveId).LocalToWorld);
|
2017-07-26 10:00:02 -04:00
|
|
|
Result.InstanceLocalPosition = Input.Position.xyz;
|
|
|
|
|
Result.PerInstanceParams = Intermediates.PerInstanceParams;
|
2018-09-25 10:11:35 -04:00
|
|
|
|
2019-06-08 17:15:34 -04:00
|
|
|
#if USE_INSTANCING_BONEMAP
|
|
|
|
|
// when using geometry collections, we can correctly compute velocities because we pass along previous transforms
|
|
|
|
|
Result.PrevFrameLocalToWorld = mul(GetInstancePrevTransform(Intermediates), GetPrimitiveData(Intermediates.PrimitiveId).PreviousLocalToWorld);
|
|
|
|
|
#else
|
|
|
|
|
// Assumes instance transform never change, which means per-instance
|
|
|
|
|
// motion will cause TAA and motion blur artifacts
|
|
|
|
|
Result.PrevFrameLocalToWorld = mul(GetInstanceTransform(Intermediates), GetPrimitiveData(Intermediates.PrimitiveId).PreviousLocalToWorld);
|
|
|
|
|
#endif // USE_INSTANCING_BONEMAP
|
2018-09-25 10:11:35 -04:00
|
|
|
#else
|
2018-12-11 22:25:04 -05:00
|
|
|
Result.PrevFrameLocalToWorld = GetPrimitiveData(Intermediates.PrimitiveId).PreviousLocalToWorld;
|
2017-07-26 10:00:02 -04:00
|
|
|
#endif // USE_INSTANCING
|
|
|
|
|
|
|
|
|
|
Result.PreSkinnedPosition = Input.Position.xyz;
|
2018-05-01 10:36:33 -04:00
|
|
|
Result.PreSkinnedNormal = TangentToLocal[2]; //TangentBias(Input.TangentZ.xyz);
|
2017-07-26 10:00:02 -04:00
|
|
|
|
2017-10-13 11:32:28 -04:00
|
|
|
#if MANUAL_VERTEX_FETCH && NUM_MATERIAL_TEXCOORDS_VERTEX
|
2018-05-01 10:36:33 -04:00
|
|
|
const uint NumFetchTexCoords = LocalVF.VertexFetch_Parameters[VF_NumTexcoords_Index];
|
2017-10-13 11:32:28 -04:00
|
|
|
UNROLL
|
|
|
|
|
for (uint CoordinateIndex = 0; CoordinateIndex < NUM_MATERIAL_TEXCOORDS_VERTEX; CoordinateIndex++)
|
2017-07-26 10:00:02 -04:00
|
|
|
{
|
2017-12-15 12:47:47 -05:00
|
|
|
// Clamp coordinates to mesh's maximum as materials can request more than are available
|
|
|
|
|
uint ClampedCoordinateIndex = min(CoordinateIndex, NumFetchTexCoords-1);
|
2018-12-11 22:25:04 -05:00
|
|
|
Result.TexCoords[CoordinateIndex] = LocalVF.VertexFetch_TexCoordBuffer[NumFetchTexCoords * (LocalVF.VertexFetch_Parameters[VF_VertexOffset] + Input.VertexId) + ClampedCoordinateIndex];
|
2017-07-26 10:00:02 -04:00
|
|
|
}
|
2017-10-13 11:32:28 -04:00
|
|
|
#elif NUM_MATERIAL_TEXCOORDS_VERTEX
|
|
|
|
|
#if GPUSKIN_PASS_THROUGH
|
2017-07-26 10:00:02 -04:00
|
|
|
UNROLL
|
2017-10-13 11:32:28 -04:00
|
|
|
for (int CoordinateIndex = 0; CoordinateIndex < NUM_MATERIAL_TEXCOORDS_VERTEX; CoordinateIndex++)
|
2017-07-26 10:00:02 -04:00
|
|
|
{
|
2017-10-13 11:32:28 -04:00
|
|
|
Result.TexCoords[CoordinateIndex] = Input.TexCoords[CoordinateIndex].xy;
|
2017-07-26 10:00:02 -04:00
|
|
|
}
|
2017-10-13 11:32:28 -04:00
|
|
|
#else
|
|
|
|
|
#if NUM_MATERIAL_TEXCOORDS_VERTEX > 1
|
|
|
|
|
UNROLL
|
|
|
|
|
for(int CoordinateIndex = 0; CoordinateIndex < NUM_MATERIAL_TEXCOORDS_VERTEX-1; CoordinateIndex+=2)
|
|
|
|
|
{
|
|
|
|
|
Result.TexCoords[CoordinateIndex] = Input.PackedTexCoords4[CoordinateIndex/2].xy;
|
|
|
|
|
if( CoordinateIndex+1 < NUM_MATERIAL_TEXCOORDS_VERTEX )
|
|
|
|
|
{
|
|
|
|
|
Result.TexCoords[CoordinateIndex+1] = Input.PackedTexCoords4[CoordinateIndex/2].zw;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif // NUM_MATERIAL_TEXCOORDS_VERTEX > 1
|
|
|
|
|
#if NUM_MATERIAL_TEXCOORDS_VERTEX % 2 == 1
|
|
|
|
|
Result.TexCoords[NUM_MATERIAL_TEXCOORDS_VERTEX-1] = Input.PackedTexCoords2;
|
|
|
|
|
#endif // NUM_MATERIAL_TEXCOORDS_VERTEX % 2 == 1
|
|
|
|
|
#endif
|
|
|
|
|
#endif //MANUAL_VERTEX_FETCH && NUM_MATERIAL_TEXCOORDS_VERTEX
|
2018-12-11 22:25:04 -05:00
|
|
|
|
|
|
|
|
Result.PrimitiveId = Intermediates.PrimitiveId;
|
2017-07-26 10:00:02 -04:00
|
|
|
return Result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if USE_SPLINEDEFORM
|
|
|
|
|
float3 SplineEvalPos(float3 StartPos, float3 StartTangent, float3 EndPos, float3 EndTangent, float A)
|
|
|
|
|
{
|
|
|
|
|
float A2 = A * A;
|
|
|
|
|
float A3 = A2 * A;
|
|
|
|
|
|
|
|
|
|
return (((2*A3)-(3*A2)+1) * StartPos) + ((A3-(2*A2)+A) * StartTangent) + ((A3-A2) * EndTangent) + (((-2*A3)+(3*A2)) * EndPos);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float3 SplineEvalDir(float3 StartPos, float3 StartTangent, float3 EndPos, float3 EndTangent, float A)
|
|
|
|
|
{
|
|
|
|
|
float3 C = (6*StartPos) + (3*StartTangent) + (3*EndTangent) - (6*EndPos);
|
|
|
|
|
float3 D = (-6*StartPos) - (4*StartTangent) - (2*EndTangent) + (6*EndPos);
|
|
|
|
|
float3 E = StartTangent;
|
|
|
|
|
|
|
|
|
|
float A2 = A * A;
|
|
|
|
|
|
|
|
|
|
return normalize((C * A2) + (D * A) + E);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Calculate full transform that defines frame along spline, given the Z of a vertex. */
|
|
|
|
|
float4x3 CalcSliceTransform(float ZPos)
|
|
|
|
|
{
|
|
|
|
|
// Find how far 'along' mesh we are
|
|
|
|
|
float Alpha = ZPos * SplineMeshScaleZ - SplineMeshMinZ;
|
|
|
|
|
|
|
|
|
|
// Apply hermite interp to Alpha if desired
|
|
|
|
|
float HermiteAlpha = SmoothInterpRollScale ? smoothstep(0.0, 1.0, Alpha) : Alpha;
|
|
|
|
|
|
|
|
|
|
// Then find the point and direction of the spline at this point along
|
2018-12-14 11:54:34 -05:00
|
|
|
float3 SplinePos = SplineEvalPos( SplineStartPos, SplineStartTangent, SplineEndPos, SplineEndTangent, Alpha );
|
|
|
|
|
float3 SplineDir = SplineEvalDir( SplineStartPos, SplineStartTangent, SplineEndPos, SplineEndTangent, Alpha );
|
2017-07-26 10:00:02 -04:00
|
|
|
|
|
|
|
|
// Find base frenet frame
|
2018-12-14 11:54:34 -05:00
|
|
|
float3 BaseXVec = normalize( cross(SplineUpDir, SplineDir) );
|
2017-07-26 10:00:02 -04:00
|
|
|
float3 BaseYVec = normalize( cross(SplineDir, BaseXVec) );
|
|
|
|
|
|
|
|
|
|
// Offset from the spline, using the frenet frame
|
|
|
|
|
float2 SliceOffset = lerp(SplineStartOffset, SplineEndOffset, HermiteAlpha);
|
|
|
|
|
SplinePos += SliceOffset.x * BaseXVec;
|
|
|
|
|
SplinePos += SliceOffset.y * BaseYVec;
|
|
|
|
|
|
|
|
|
|
// Apply roll to frame around spline
|
|
|
|
|
float UseRoll = lerp(SplineStartRoll, SplineEndRoll, HermiteAlpha);
|
|
|
|
|
float SinAng, CosAng;
|
|
|
|
|
sincos(UseRoll, SinAng, CosAng);
|
|
|
|
|
float3 XVec = (CosAng * BaseXVec) - (SinAng * BaseYVec);
|
|
|
|
|
float3 YVec = (CosAng * BaseYVec) + (SinAng * BaseXVec);
|
|
|
|
|
|
|
|
|
|
// Find scale at this point along spline
|
|
|
|
|
float2 UseScale = lerp(SplineStartScale, SplineEndScale, HermiteAlpha);
|
|
|
|
|
|
|
|
|
|
XVec *= UseScale.x;
|
|
|
|
|
YVec *= UseScale.y;
|
|
|
|
|
|
|
|
|
|
// Build overall transform
|
2018-12-14 11:54:34 -05:00
|
|
|
float3x3 SliceTransform3 = mul(transpose(float3x3(SplineMeshDir, SplineMeshX, SplineMeshY)), float3x3(float3(0,0,0), XVec, YVec));
|
2017-07-26 10:00:02 -04:00
|
|
|
float4x3 SliceTransform = float4x3(SliceTransform3[0], SliceTransform3[1], SliceTransform3[2], SplinePos);
|
|
|
|
|
|
|
|
|
|
return SliceTransform;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Calculate rotation matrix that defines frame along spline, given the Z of a vertex. */
|
|
|
|
|
half3x3 CalcSliceRot(float ZPos)
|
|
|
|
|
{
|
|
|
|
|
// Find how far 'along' mesh we are
|
|
|
|
|
half Alpha = ZPos * SplineMeshScaleZ - SplineMeshMinZ;
|
|
|
|
|
|
|
|
|
|
// Apply hermite interp to Alpha if desired
|
|
|
|
|
half HermiteAlpha = SmoothInterpRollScale ? smoothstep(0.0, 1.0, Alpha) : Alpha;
|
|
|
|
|
|
|
|
|
|
// Then find the point and direction of the spline at this point along
|
2018-12-14 11:54:34 -05:00
|
|
|
half3 SplineDir = SplineEvalDir( SplineStartPos, SplineStartTangent, SplineEndPos, SplineEndTangent, Alpha );
|
2017-07-26 10:00:02 -04:00
|
|
|
|
|
|
|
|
// Find base frenet frame
|
2018-12-14 11:54:34 -05:00
|
|
|
half3 BaseXVec = normalize( cross(SplineUpDir, (half3)SplineDir) );
|
2017-07-26 10:00:02 -04:00
|
|
|
half3 BaseYVec = normalize( cross((half3)SplineDir, BaseXVec) );
|
|
|
|
|
|
|
|
|
|
// Apply roll to frame around spline
|
|
|
|
|
half UseRoll = lerp((half)SplineStartRoll, (half)SplineEndRoll, HermiteAlpha);
|
|
|
|
|
half SinAng, CosAng;
|
|
|
|
|
sincos(UseRoll, SinAng, CosAng);
|
|
|
|
|
half3 XVec = (CosAng * BaseXVec) - (SinAng * BaseYVec);
|
|
|
|
|
half3 YVec = (CosAng * BaseYVec) + (SinAng * BaseXVec);
|
|
|
|
|
|
|
|
|
|
// Find scale at this point along spline
|
|
|
|
|
half2 UseScale = lerp(SplineStartScale, SplineEndScale, HermiteAlpha);
|
|
|
|
|
|
|
|
|
|
XVec *= sign(UseScale.x);
|
|
|
|
|
YVec *= sign(UseScale.y);
|
|
|
|
|
|
|
|
|
|
// Build rotation transform
|
2018-12-14 11:54:34 -05:00
|
|
|
half3x3 SliceTransform = mul(transpose(half3x3(SplineMeshDir, SplineMeshX, SplineMeshY)), half3x3(SplineDir, XVec, YVec));
|
2017-07-26 10:00:02 -04:00
|
|
|
|
|
|
|
|
return SliceTransform;
|
|
|
|
|
}
|
|
|
|
|
#endif // USE_SPLINEDEFORM
|
|
|
|
|
|
|
|
|
|
#if USE_INSTANCING
|
2018-12-11 22:25:04 -05:00
|
|
|
float4 CalcWorldPosition(float4 Position, float4x4 InstanceTransform, uint PrimitiveId)
|
2017-07-26 10:00:02 -04:00
|
|
|
#else
|
2018-12-11 22:25:04 -05:00
|
|
|
float4 CalcWorldPosition(float4 Position, uint PrimitiveId)
|
2017-07-26 10:00:02 -04:00
|
|
|
#endif // USE_INSTANCING
|
|
|
|
|
{
|
|
|
|
|
#if USE_INSTANCING
|
2018-12-11 22:25:04 -05:00
|
|
|
return TransformLocalToTranslatedWorld(mul(Position, InstanceTransform).xyz, PrimitiveId);
|
2017-07-26 10:00:02 -04:00
|
|
|
#elif USE_SPLINEDEFORM
|
|
|
|
|
/*
|
|
|
|
|
// Make transform for this point along spline
|
2018-12-14 11:54:34 -05:00
|
|
|
float4x3 SliceTransform = CalcSliceTransform(dot(Position.xyz, SplineMeshDir));
|
2017-07-26 10:00:02 -04:00
|
|
|
|
|
|
|
|
// Transform into mesh space
|
|
|
|
|
float4 LocalPos = float4(mul(Position, SliceTransform), Position.w);
|
|
|
|
|
// Transform from mesh to world space
|
|
|
|
|
return TransformLocalToTranslatedWorld(LocalPos.xyz);
|
|
|
|
|
*/
|
2018-12-14 11:54:34 -05:00
|
|
|
return INVARIANT(TransformLocalToTranslatedWorld(float3(mul(Position, CalcSliceTransform(dot(Position.xyz, SplineMeshDir))).xyz), PrimitiveId));
|
2017-07-26 10:00:02 -04:00
|
|
|
#else
|
2018-12-11 22:25:04 -05:00
|
|
|
return TransformLocalToTranslatedWorld(Position.xyz, PrimitiveId);
|
2017-07-26 10:00:02 -04:00
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-13 11:32:28 -04:00
|
|
|
half3x3 CalcTangentToLocal(FVertexFactoryInput Input, out float TangentSign)
|
2017-07-26 10:00:02 -04:00
|
|
|
{
|
|
|
|
|
half3x3 Result;
|
|
|
|
|
|
2017-10-13 11:32:28 -04:00
|
|
|
#if MANUAL_VERTEX_FETCH
|
2018-12-11 22:25:04 -05:00
|
|
|
half3 TangentInputX = LocalVF.VertexFetch_PackedTangentsBuffer[2 * (LocalVF.VertexFetch_Parameters[VF_VertexOffset] + Input.VertexId) + 0].xyz;
|
|
|
|
|
half4 TangentInputZ = LocalVF.VertexFetch_PackedTangentsBuffer[2 * (LocalVF.VertexFetch_Parameters[VF_VertexOffset] + Input.VertexId) + 1].xyzw;
|
2017-10-13 11:32:28 -04:00
|
|
|
#else
|
|
|
|
|
half3 TangentInputX = Input.TangentX;
|
|
|
|
|
half4 TangentInputZ = Input.TangentZ;
|
|
|
|
|
#endif
|
|
|
|
|
|
2018-05-01 10:36:33 -04:00
|
|
|
#ifdef GPUSKIN_PASS_THROUGH
|
|
|
|
|
half3 TangentX = TangentInputX;
|
|
|
|
|
half4 TangentZ = TangentInputZ;
|
|
|
|
|
#else
|
2017-10-13 11:32:28 -04:00
|
|
|
half3 TangentX = TangentBias(TangentInputX);
|
|
|
|
|
half4 TangentZ = TangentBias(TangentInputZ);
|
2018-05-01 10:36:33 -04:00
|
|
|
#endif
|
|
|
|
|
|
2017-10-13 11:32:28 -04:00
|
|
|
TangentSign = TangentZ.w;
|
2017-07-26 10:00:02 -04:00
|
|
|
|
|
|
|
|
#if USE_SPLINEDEFORM
|
|
|
|
|
// Make slice rotation matrix, and use that to transform tangents
|
2018-12-14 11:54:34 -05:00
|
|
|
half3x3 SliceRot = CalcSliceRot(dot(Input.Position.xyz, SplineMeshDir));
|
2017-07-26 10:00:02 -04:00
|
|
|
|
|
|
|
|
TangentX = mul(TangentX, SliceRot);
|
|
|
|
|
TangentZ.xyz = mul(TangentZ.xyz, SliceRot);
|
|
|
|
|
#endif // USE_SPLINEDEFORM
|
|
|
|
|
|
|
|
|
|
// derive the binormal by getting the cross product of the normal and tangent
|
|
|
|
|
half3 TangentY = cross(TangentZ.xyz, TangentX) * TangentZ.w;
|
|
|
|
|
|
|
|
|
|
// Recalculate TangentX off of the other two vectors
|
|
|
|
|
// This corrects quantization error since TangentX was passed in as a quantized vertex input
|
|
|
|
|
// The error shows up most in specular off of a mesh with a smoothed UV seam (normal is smooth, but tangents vary across the seam)
|
|
|
|
|
Result[0] = cross(TangentY, TangentZ.xyz) * TangentZ.w;
|
|
|
|
|
Result[1] = TangentY;
|
|
|
|
|
Result[2] = TangentZ.xyz;
|
|
|
|
|
|
|
|
|
|
return Result;
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-13 11:32:28 -04:00
|
|
|
half3x3 CalcTangentToWorld(FVertexFactoryIntermediates Intermediates, half3x3 TangentToLocal)
|
2017-07-26 10:00:02 -04:00
|
|
|
{
|
|
|
|
|
#if USE_INSTANCING
|
2018-12-11 22:25:04 -05:00
|
|
|
half3x3 InstanceToWorld = mul(GetInstanceToLocal3x3(Intermediates), GetLocalToWorld3x3(Intermediates.PrimitiveId));
|
2017-07-26 10:00:02 -04:00
|
|
|
// remove scaling
|
|
|
|
|
InstanceToWorld[0] = normalize(InstanceToWorld[0]);
|
|
|
|
|
InstanceToWorld[1] = normalize(InstanceToWorld[1]);
|
|
|
|
|
InstanceToWorld[2] = normalize(InstanceToWorld[2]);
|
|
|
|
|
half3x3 TangentToWorld = mul(TangentToLocal, InstanceToWorld);
|
|
|
|
|
#else
|
2018-12-11 22:25:04 -05:00
|
|
|
half3x3 TangentToWorld = CalcTangentToWorldNoScale(Intermediates, TangentToLocal);
|
2017-07-26 10:00:02 -04:00
|
|
|
#endif // USE_INSTANCING
|
|
|
|
|
return TangentToWorld;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FVertexFactoryIntermediates GetVertexFactoryIntermediates(FVertexFactoryInput Input)
|
|
|
|
|
{
|
|
|
|
|
FVertexFactoryIntermediates Intermediates;
|
|
|
|
|
|
2018-12-11 22:25:04 -05:00
|
|
|
#if VF_USE_PRIMITIVE_SCENE_DATA
|
|
|
|
|
Intermediates.PrimitiveId = Input.PrimitiveId;
|
|
|
|
|
#else
|
|
|
|
|
Intermediates.PrimitiveId = 0;
|
|
|
|
|
#endif
|
|
|
|
|
|
2017-10-13 11:32:28 -04:00
|
|
|
#if MANUAL_VERTEX_FETCH
|
2018-12-11 22:25:04 -05:00
|
|
|
Intermediates.Color = LocalVF.VertexFetch_ColorComponentsBuffer[(LocalVF.VertexFetch_Parameters[VF_VertexOffset] + Input.VertexId) & LocalVF.VertexFetch_Parameters[VF_ColorIndexMask_Index]] FMANUALFETCH_COLOR_COMPONENT_SWIZZLE; // Swizzle vertex color.
|
2017-10-13 11:32:28 -04:00
|
|
|
#else
|
|
|
|
|
Intermediates.Color = Input.Color FCOLOR_COMPONENT_SWIZZLE; // Swizzle vertex color.
|
|
|
|
|
#endif
|
|
|
|
|
|
2019-06-08 17:15:34 -04:00
|
|
|
#if USE_INSTANCING && !USE_INSTANCING_EMULATED && MANUAL_VERTEX_FETCH && !USE_INSTANCING_BONEMAP
|
2019-01-17 05:02:52 -05:00
|
|
|
uint InstanceId = GetInstanceId(Input.InstanceId);
|
|
|
|
|
Intermediates.InstanceTransform1 = VertexFetch_InstanceTransformBuffer[3 * (InstanceId + InstanceOffset) + 0];
|
|
|
|
|
Intermediates.InstanceTransform2 = VertexFetch_InstanceTransformBuffer[3 * (InstanceId + InstanceOffset) + 1];
|
|
|
|
|
Intermediates.InstanceTransform3 = VertexFetch_InstanceTransformBuffer[3 * (InstanceId + InstanceOffset) + 2];
|
|
|
|
|
Intermediates.InstanceOrigin = VertexFetch_InstanceOriginBuffer[(InstanceId + InstanceOffset)];
|
|
|
|
|
Intermediates.InstanceLightmapAndShadowMapUVBias = VertexFetch_InstanceLightmapBuffer[(InstanceId + InstanceOffset)];
|
2019-06-08 17:15:34 -04:00
|
|
|
#elif !USE_INSTANCING_EMULATED && MANUAL_VERTEX_FETCH && USE_INSTANCING_BONEMAP
|
|
|
|
|
uint InstanceIndex = VertexFetch_InstanceBoneMapBuffer[LocalVF.VertexFetch_Parameters[VF_VertexOffset] + Input.VertexId];
|
|
|
|
|
Intermediates.InstanceTransform1 = VertexFetch_InstanceTransformBuffer[4 * InstanceIndex + 0];
|
|
|
|
|
Intermediates.InstanceTransform2 = VertexFetch_InstanceTransformBuffer[4 * InstanceIndex + 1];
|
|
|
|
|
Intermediates.InstanceTransform3 = VertexFetch_InstanceTransformBuffer[4 * InstanceIndex + 2];
|
|
|
|
|
Intermediates.InstanceOrigin = VertexFetch_InstanceTransformBuffer[4 * InstanceIndex + 3];
|
|
|
|
|
|
|
|
|
|
Intermediates.InstancePrevTransform1 = VertexFetch_InstancePrevTransformBuffer[4 * InstanceIndex + 0];
|
|
|
|
|
Intermediates.InstancePrevTransform2 = VertexFetch_InstancePrevTransformBuffer[4 * InstanceIndex + 1];
|
|
|
|
|
Intermediates.InstancePrevTransform3 = VertexFetch_InstancePrevTransformBuffer[4 * InstanceIndex + 2];
|
|
|
|
|
Intermediates.InstancePrevOrigin = VertexFetch_InstancePrevTransformBuffer[4 * InstanceIndex + 3];
|
|
|
|
|
|
|
|
|
|
Intermediates.InstanceLightmapAndShadowMapUVBias = float4(0,0,0,0);
|
2017-10-13 11:32:28 -04:00
|
|
|
#elif USE_INSTANCING && !USE_INSTANCING_EMULATED
|
2018-07-12 10:41:46 -04:00
|
|
|
Intermediates.InstanceTransform1 = Input.InstanceTransform1;
|
|
|
|
|
Intermediates.InstanceTransform2 = Input.InstanceTransform2;
|
|
|
|
|
Intermediates.InstanceTransform3 = Input.InstanceTransform3;
|
2017-10-13 11:32:28 -04:00
|
|
|
Intermediates.InstanceOrigin = Input.InstanceOrigin;
|
|
|
|
|
Intermediates.InstanceLightmapAndShadowMapUVBias = Input.InstanceLightmapAndShadowMapUVBias;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
float TangentSign;
|
|
|
|
|
Intermediates.TangentToLocal = CalcTangentToLocal(Input, TangentSign);
|
|
|
|
|
Intermediates.TangentToWorld = CalcTangentToWorld(Intermediates,Intermediates.TangentToLocal);
|
2018-12-11 22:25:04 -05:00
|
|
|
Intermediates.TangentToWorldSign = TangentSign * GetPrimitiveData(Intermediates.PrimitiveId).InvNonUniformScaleAndDeterminantSign.w;
|
2017-07-26 10:00:02 -04:00
|
|
|
|
2019-06-08 17:15:34 -04:00
|
|
|
#if USE_INSTANCING && !USE_INSTANCING_BONEMAP
|
2017-07-26 10:00:02 -04:00
|
|
|
// x = per-instance random, y = per-instance fade out factor, z = zero or one depending of if it is shown at all, w is dither cutoff
|
|
|
|
|
|
|
|
|
|
// PerInstanceParams.z stores a hide/show flag for this instance
|
2017-10-13 11:32:28 -04:00
|
|
|
float SelectedValue = GetInstanceSelected(Intermediates);
|
|
|
|
|
Intermediates.PerInstanceParams.x = GetInstanceRandom(Intermediates);
|
2018-12-11 22:25:04 -05:00
|
|
|
float3 InstanceLocation = TransformLocalToWorld(GetInstanceOrigin(Intermediates), Intermediates.PrimitiveId).xyz;
|
2017-07-26 10:00:02 -04:00
|
|
|
Intermediates.PerInstanceParams.y = 1.0 - saturate((length(InstanceLocation + ResolvedView.PreViewTranslation.xyz) - InstancingFadeOutParams.x) * InstancingFadeOutParams.y);
|
|
|
|
|
// InstancingFadeOutParams.z,w are RenderSelected and RenderDeselected respectively.
|
|
|
|
|
Intermediates.PerInstanceParams.z = InstancingFadeOutParams.z * SelectedValue + InstancingFadeOutParams.w * (1-SelectedValue);
|
|
|
|
|
#if USE_DITHERED_LOD_TRANSITION
|
|
|
|
|
float RandomLOD = InstancingViewZCompareZero.w * Intermediates.PerInstanceParams.x;
|
|
|
|
|
float ViewZZero = length(InstanceLocation - InstancingWorldViewOriginZero.xyz) + RandomLOD;
|
|
|
|
|
float ViewZOne = length(InstanceLocation - InstancingWorldViewOriginOne.xyz) + RandomLOD;
|
|
|
|
|
Intermediates.PerInstanceParams.w =
|
|
|
|
|
dot(float3(ViewZZero.xxx > InstancingViewZCompareZero.xyz), InstancingViewZConstant.xyz) * InstancingWorldViewOriginZero.w +
|
|
|
|
|
dot(float3(ViewZOne.xxx > InstancingViewZCompareOne.xyz), InstancingViewZConstant.xyz) * InstancingWorldViewOriginOne.w;
|
|
|
|
|
Intermediates.PerInstanceParams.z *= abs(Intermediates.PerInstanceParams.w) < .999;
|
|
|
|
|
#else
|
|
|
|
|
Intermediates.PerInstanceParams.w = 0;
|
|
|
|
|
#endif
|
2019-06-08 17:15:34 -04:00
|
|
|
#elif USE_INSTANCING && USE_INSTANCING_BONEMAP
|
|
|
|
|
Intermediates.PerInstanceParams.x = 0;
|
|
|
|
|
Intermediates.PerInstanceParams.y = 1;
|
|
|
|
|
Intermediates.PerInstanceParams.z = 1;
|
|
|
|
|
Intermediates.PerInstanceParams.w = 0;
|
2017-07-26 10:00:02 -04:00
|
|
|
#endif // USE_INSTANCING
|
|
|
|
|
return Intermediates;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the 3x3 tangent basis vectors for this vertex factory
|
|
|
|
|
* this vertex factory will calculate the binormal on-the-fly
|
|
|
|
|
*
|
|
|
|
|
* @param Input - vertex input stream structure
|
|
|
|
|
* @return 3x3 matrix
|
|
|
|
|
*/
|
|
|
|
|
half3x3 VertexFactoryGetTangentToLocal( FVertexFactoryInput Input, FVertexFactoryIntermediates Intermediates )
|
|
|
|
|
{
|
|
|
|
|
return Intermediates.TangentToLocal;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// @return translated world position
|
|
|
|
|
float4 VertexFactoryGetWorldPosition(FVertexFactoryInput Input, FVertexFactoryIntermediates Intermediates)
|
|
|
|
|
{
|
|
|
|
|
#if USE_INSTANCING
|
2018-05-23 21:04:31 -04:00
|
|
|
// Workaround for FORT-70572. It turns out on old Nvidia (AMD?) drivers, SV_VertexID must be used if
|
|
|
|
|
// SV_InstanceID is used. Otherwise, SV_InstanceID will get weird (SV_VertexID?) values
|
|
|
|
|
#if SM4_PROFILE && MANUAL_VERTEX_FETCH
|
|
|
|
|
float4 Position = Input.Position + Input.VertexId * asfloat(0x00800001);
|
|
|
|
|
#else
|
|
|
|
|
float4 Position = Input.Position;
|
|
|
|
|
#endif
|
2018-12-11 22:25:04 -05:00
|
|
|
return CalcWorldPosition(Position, GetInstanceTransform(Intermediates), Intermediates.PrimitiveId) * Intermediates.PerInstanceParams.z;
|
2017-07-26 10:00:02 -04:00
|
|
|
#else
|
2018-12-11 22:25:04 -05:00
|
|
|
return CalcWorldPosition(Input.Position, Intermediates.PrimitiveId);
|
2017-07-26 10:00:02 -04:00
|
|
|
#endif // USE_INSTANCING
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
// Initialize the whole struct to 0
|
|
|
|
|
// Really only the last two components of the packed UVs have the opportunity to be uninitialized
|
|
|
|
|
Interpolants = (FVertexFactoryInterpolantsVSToPS)0;
|
|
|
|
|
|
|
|
|
|
#if NUM_TEX_COORD_INTERPOLATORS
|
|
|
|
|
float2 CustomizedUVs[NUM_TEX_COORD_INTERPOLATORS];
|
|
|
|
|
GetMaterialCustomizedUVs(VertexParameters, CustomizedUVs);
|
|
|
|
|
GetCustomInterpolators(VertexParameters, CustomizedUVs);
|
|
|
|
|
|
|
|
|
|
UNROLL
|
|
|
|
|
for (int CoordinateIndex = 0; CoordinateIndex < NUM_TEX_COORD_INTERPOLATORS; CoordinateIndex++)
|
|
|
|
|
{
|
|
|
|
|
SetUV(Interpolants, CoordinateIndex, CustomizedUVs[CoordinateIndex]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#elif NUM_MATERIAL_TEXCOORDS_VERTEX == 0 && USE_PARTICLE_SUBUVS
|
2017-10-13 11:32:28 -04:00
|
|
|
#if MANUAL_VERTEX_FETCH
|
2018-12-11 22:25:04 -05:00
|
|
|
SetUV(Interpolants, 0, LocalVF.VertexFetch_TexCoordBuffer[LocalVF.VertexFetch_Parameters[VF_NumTexcoords_Index] * (LocalVF.VertexFetch_Parameters[VF_VertexOffset] + Input.VertexId)]);
|
2017-10-13 11:32:28 -04:00
|
|
|
#else
|
|
|
|
|
SetUV(Interpolants, 0, Input.TexCoords[0]);
|
|
|
|
|
#endif
|
2017-07-26 10:00:02 -04:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if NEEDS_LIGHTMAP_COORDINATE
|
|
|
|
|
float2 LightMapCoordinate = 0;
|
|
|
|
|
float2 ShadowMapCoordinate = 0;
|
2017-10-13 11:32:28 -04:00
|
|
|
#if MANUAL_VERTEX_FETCH
|
2018-12-11 22:25:04 -05:00
|
|
|
float2 LightMapCoordinateInput = LocalVF.VertexFetch_TexCoordBuffer[LocalVF.VertexFetch_Parameters[VF_NumTexcoords_Index] * (LocalVF.VertexFetch_Parameters[VF_VertexOffset] + Input.VertexId) + LocalVF.VertexFetch_Parameters[FV_LightMapIndex_Index]];
|
2017-10-13 11:32:28 -04:00
|
|
|
#else
|
|
|
|
|
float2 LightMapCoordinateInput = Input.LightMapCoordinate;
|
|
|
|
|
#endif
|
2017-07-26 10:00:02 -04:00
|
|
|
|
2018-12-11 22:25:04 -05:00
|
|
|
uint LightmapDataIndex = 0;
|
|
|
|
|
|
|
|
|
|
#if VF_USE_PRIMITIVE_SCENE_DATA
|
|
|
|
|
LightmapDataIndex = GetPrimitiveData(Intermediates.PrimitiveId).LightmapDataIndex + LocalVF.LODLightmapDataIndex;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
float4 LightMapCoordinateScaleBias = GetLightmapData(LightmapDataIndex).LightMapCoordinateScaleBias;
|
|
|
|
|
|
2017-07-26 10:00:02 -04:00
|
|
|
#if USE_INSTANCING
|
2018-12-11 22:25:04 -05:00
|
|
|
LightMapCoordinate = LightMapCoordinateInput * LightMapCoordinateScaleBias.xy + GetInstanceLightMapBias(Intermediates);
|
2017-07-26 10:00:02 -04:00
|
|
|
#else
|
2018-12-11 22:25:04 -05:00
|
|
|
LightMapCoordinate = LightMapCoordinateInput * LightMapCoordinateScaleBias.xy + LightMapCoordinateScaleBias.zw;
|
2017-07-26 10:00:02 -04:00
|
|
|
#endif
|
|
|
|
|
#if STATICLIGHTING_TEXTUREMASK
|
2018-12-11 22:25:04 -05:00
|
|
|
float4 ShadowMapCoordinateScaleBias = GetLightmapData(LightmapDataIndex).ShadowMapCoordinateScaleBias;
|
|
|
|
|
|
2017-07-26 10:00:02 -04:00
|
|
|
#if USE_INSTANCING
|
2018-12-11 22:25:04 -05:00
|
|
|
ShadowMapCoordinate = LightMapCoordinateInput * ShadowMapCoordinateScaleBias.xy + GetInstanceShadowMapBias(Intermediates);
|
2017-07-26 10:00:02 -04:00
|
|
|
#else
|
2018-12-11 22:25:04 -05:00
|
|
|
ShadowMapCoordinate = LightMapCoordinateInput * ShadowMapCoordinateScaleBias.xy + ShadowMapCoordinateScaleBias.zw;
|
2017-07-26 10:00:02 -04:00
|
|
|
#endif
|
|
|
|
|
#endif // STATICLIGHTING_TEXTUREMASK
|
|
|
|
|
|
|
|
|
|
SetLightMapCoordinate(Interpolants, LightMapCoordinate, ShadowMapCoordinate);
|
2018-12-11 22:25:04 -05:00
|
|
|
SetLightmapDataIndex(Interpolants, LightmapDataIndex);
|
2017-07-26 10:00:02 -04:00
|
|
|
#endif // NEEDS_LIGHTMAP_COORDINATE
|
|
|
|
|
|
|
|
|
|
SetTangents(Interpolants, Intermediates.TangentToWorld[0], Intermediates.TangentToWorld[2], Intermediates.TangentToWorldSign);
|
|
|
|
|
SetColor(Interpolants, Intermediates.Color);
|
|
|
|
|
#if USE_INSTANCING
|
|
|
|
|
Interpolants.PerInstanceParams = Intermediates.PerInstanceParams;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if INSTANCED_STEREO
|
2019-01-17 05:02:52 -05:00
|
|
|
Interpolants.EyeIndex = 0;
|
2017-07-26 10:00:02 -04:00
|
|
|
#endif
|
|
|
|
|
|
2018-12-11 22:25:04 -05:00
|
|
|
SetPrimitiveId(Interpolants, Intermediates.PrimitiveId);
|
|
|
|
|
|
2017-07-26 10:00:02 -04:00
|
|
|
return Interpolants;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** for depth-only pass */
|
|
|
|
|
float4 VertexFactoryGetWorldPosition(FPositionOnlyVertexFactoryInput Input)
|
|
|
|
|
{
|
2017-10-13 11:32:28 -04:00
|
|
|
float4 Position = Input.Position;
|
2018-12-11 22:25:04 -05:00
|
|
|
|
|
|
|
|
#if VF_USE_PRIMITIVE_SCENE_DATA
|
|
|
|
|
uint PrimitiveId = Input.PrimitiveId;
|
|
|
|
|
#else
|
|
|
|
|
uint PrimitiveId = 0;
|
|
|
|
|
#endif
|
2017-10-13 11:32:28 -04:00
|
|
|
|
2017-07-26 10:00:02 -04:00
|
|
|
#if USE_INSTANCING
|
2018-12-11 22:25:04 -05:00
|
|
|
return CalcWorldPosition(Position, GetInstanceTransform(Input), PrimitiveId);
|
2017-07-26 10:00:02 -04:00
|
|
|
#else
|
2018-12-11 22:25:04 -05:00
|
|
|
return CalcWorldPosition(Position, PrimitiveId);
|
2017-07-26 10:00:02 -04:00
|
|
|
#endif // USE_INSTANCING
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Information when using pass through to get the previous position, as no matrix is available/needed
|
|
|
|
|
#if GPUSKIN_PASS_THROUGH
|
2017-10-13 11:32:28 -04:00
|
|
|
Buffer<float> GPUSkinCachePreviousPositionBuffer;
|
2017-07-26 10:00:02 -04:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
// @return previous translated world position
|
|
|
|
|
float4 VertexFactoryGetPreviousWorldPosition(FVertexFactoryInput Input, FVertexFactoryIntermediates Intermediates)
|
|
|
|
|
{
|
2018-12-11 22:25:04 -05:00
|
|
|
float4x4 PreviousLocalToWorldTranslated = GetPrimitiveData(Intermediates.PrimitiveId).PreviousLocalToWorld;
|
2017-07-26 10:00:02 -04:00
|
|
|
PreviousLocalToWorldTranslated[3][0] += ResolvedView.PrevPreViewTranslation.x;
|
|
|
|
|
PreviousLocalToWorldTranslated[3][1] += ResolvedView.PrevPreViewTranslation.y;
|
|
|
|
|
PreviousLocalToWorldTranslated[3][2] += ResolvedView.PrevPreViewTranslation.z;
|
|
|
|
|
|
2019-06-08 17:15:34 -04:00
|
|
|
#if USE_INSTANCING && !USE_INSTANCING_BONEMAP
|
2017-10-13 11:32:28 -04:00
|
|
|
float4x4 InstanceTransform = GetInstanceTransform(Intermediates);
|
2017-07-26 10:00:02 -04:00
|
|
|
return mul(mul(Input.Position, InstanceTransform), PreviousLocalToWorldTranslated);
|
2019-06-08 17:15:34 -04:00
|
|
|
#elif USE_INSTANCING && USE_INSTANCING_BONEMAP
|
|
|
|
|
float4x4 InstanceTransform = GetInstancePrevTransform(Intermediates);
|
|
|
|
|
return mul(mul(Input.Position, InstanceTransform), PreviousLocalToWorldTranslated);
|
2017-07-26 10:00:02 -04:00
|
|
|
#elif GPUSKIN_PASS_THROUGH
|
2017-10-13 11:32:28 -04:00
|
|
|
uint Offset = Input.VertexId * 3;
|
2017-07-26 10:00:02 -04:00
|
|
|
float3 PreviousPos;
|
2017-10-13 11:32:28 -04:00
|
|
|
PreviousPos.x = GPUSkinCachePreviousPositionBuffer[Offset + 0];
|
|
|
|
|
PreviousPos.y = GPUSkinCachePreviousPositionBuffer[Offset + 1];
|
|
|
|
|
PreviousPos.z = GPUSkinCachePreviousPositionBuffer[Offset + 2];
|
2017-07-26 10:00:02 -04:00
|
|
|
return mul(float4(PreviousPos, 1), PreviousLocalToWorldTranslated);
|
|
|
|
|
#elif USE_SPLINEDEFORM
|
|
|
|
|
// Just like CalcWorldPosition...
|
2018-12-14 11:54:34 -05:00
|
|
|
float4x3 SliceTransform = CalcSliceTransform(dot(Input.Position.xyz, SplineMeshDir));
|
2017-07-26 10:00:02 -04:00
|
|
|
|
|
|
|
|
// Transform into mesh space
|
|
|
|
|
float4 LocalPos = float4(mul(Input.Position, SliceTransform), Input.Position.w);
|
|
|
|
|
|
|
|
|
|
return mul(LocalPos, PreviousLocalToWorldTranslated);
|
|
|
|
|
#else
|
|
|
|
|
return mul(Input.Position, PreviousLocalToWorldTranslated);
|
|
|
|
|
#endif // USE_INSTANCING
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if USING_TESSELLATION
|
|
|
|
|
struct FVertexFactoryInterpolantsVSToDS
|
|
|
|
|
{
|
|
|
|
|
FVertexFactoryInterpolantsVSToPS InterpolantsVSToPS;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
float2 VertexFactoryGetTextureCoordinateDS( FVertexFactoryInterpolantsVSToDS Interpolants )
|
|
|
|
|
{
|
|
|
|
|
#if NUM_MATERIAL_TEXCOORDS
|
|
|
|
|
return Interpolants.InterpolantsVSToPS.TexCoords[0].xy;
|
|
|
|
|
#else // #if NUM_MATERIAL_TEXCOORDS
|
|
|
|
|
return float2(0,0);
|
|
|
|
|
#endif // #if NUM_MATERIAL_TEXCOORDS
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FVertexFactoryInterpolantsVSToPS VertexFactoryAssignInterpolants(FVertexFactoryInterpolantsVSToDS Input)
|
|
|
|
|
{
|
|
|
|
|
return Input.InterpolantsVSToPS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Converts from vertex factory specific interpolants to a FMaterialTessellationParameters, which is used by material inputs. */
|
|
|
|
|
FMaterialTessellationParameters GetMaterialTessellationParameters(FVertexFactoryInterpolantsVSToDS Interpolants, float3 CameraLocalWorldPosition)
|
|
|
|
|
{
|
|
|
|
|
FMaterialTessellationParameters Result;
|
|
|
|
|
#if NUM_TEX_COORD_INTERPOLATORS
|
|
|
|
|
UNROLL
|
|
|
|
|
for(int CoordinateIndex = 0;CoordinateIndex < NUM_TEX_COORD_INTERPOLATORS;CoordinateIndex += 2)
|
|
|
|
|
{
|
|
|
|
|
Result.TexCoords[CoordinateIndex] = Interpolants.InterpolantsVSToPS.TexCoords[CoordinateIndex/2].xy;
|
|
|
|
|
if(CoordinateIndex + 1 < NUM_TEX_COORD_INTERPOLATORS)
|
|
|
|
|
{
|
|
|
|
|
Result.TexCoords[CoordinateIndex + 1] = Interpolants.InterpolantsVSToPS.TexCoords[CoordinateIndex/2].zw;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif // NUM_TEX_COORD_INTERPOLATORS
|
|
|
|
|
|
|
|
|
|
half3 TangentToWorld0 = Interpolants.InterpolantsVSToPS.TangentToWorld0.xyz;
|
|
|
|
|
half4 TangentToWorld2 = Interpolants.InterpolantsVSToPS.TangentToWorld2;
|
|
|
|
|
|
|
|
|
|
#if INTERPOLATE_VERTEX_COLOR
|
|
|
|
|
Result.VertexColor = Interpolants.InterpolantsVSToPS.Color;
|
|
|
|
|
#endif // INTERPOLATE_VERTEX_COLOR
|
|
|
|
|
|
|
|
|
|
Result.TangentToWorld = AssembleTangentToWorld( TangentToWorld0, TangentToWorld2 );
|
|
|
|
|
|
|
|
|
|
Result.TangentToWorldPreScale = 1;
|
|
|
|
|
|
|
|
|
|
Result.WorldPosition = CameraLocalWorldPosition + ResolvedView.WorldCameraOrigin;
|
2018-12-11 22:25:04 -05:00
|
|
|
Result.PrimitiveId = GetPrimitiveId(Interpolants.InterpolantsVSToPS);
|
2017-07-26 10:00:02 -04:00
|
|
|
return Result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FVertexFactoryInterpolantsVSToDS VertexFactoryGetInterpolantsVSToDS(FVertexFactoryInput Input, FVertexFactoryIntermediates Intermediates, FMaterialVertexParameters VertexParameters)
|
|
|
|
|
{
|
|
|
|
|
FVertexFactoryInterpolantsVSToDS Interpolants;
|
|
|
|
|
Interpolants.InterpolantsVSToPS = VertexFactoryGetInterpolantsVSToPS(Input, Intermediates, VertexParameters);
|
|
|
|
|
return Interpolants;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FVertexFactoryInterpolantsVSToDS VertexFactoryInterpolate(FVertexFactoryInterpolantsVSToDS a, float aInterp, FVertexFactoryInterpolantsVSToDS b, float bInterp)
|
|
|
|
|
{
|
|
|
|
|
FVertexFactoryInterpolantsVSToDS O;
|
2018-12-11 22:25:04 -05:00
|
|
|
|
2018-12-18 21:41:17 -05:00
|
|
|
#if VF_USE_PRIMITIVE_SCENE_DATA
|
2018-12-11 22:25:04 -05:00
|
|
|
O.InterpolantsVSToPS.PrimitiveId = a.InterpolantsVSToPS.PrimitiveId;
|
2018-12-18 21:41:17 -05:00
|
|
|
#if NEEDS_LIGHTMAP_COORDINATE
|
|
|
|
|
O.InterpolantsVSToPS.LightmapDataIndex = a.InterpolantsVSToPS.LightmapDataIndex;
|
|
|
|
|
#endif
|
|
|
|
|
#endif
|
2017-07-26 10:00:02 -04:00
|
|
|
// Do we really need to interpolate TangentToWorld2 here? It should be replaced by the
|
|
|
|
|
// interpolated normal from 'whatever' interpolation scheme we're using
|
|
|
|
|
|
|
|
|
|
TESSELLATION_INTERPOLATE_MEMBER(InterpolantsVSToPS.TangentToWorld0.xyz);
|
|
|
|
|
TESSELLATION_INTERPOLATE_MEMBER(InterpolantsVSToPS.TangentToWorld2);
|
|
|
|
|
#if INTERPOLATE_VERTEX_COLOR
|
|
|
|
|
TESSELLATION_INTERPOLATE_MEMBER(InterpolantsVSToPS.Color);
|
|
|
|
|
#endif
|
|
|
|
|
#if USE_INSTANCING
|
|
|
|
|
TESSELLATION_INTERPOLATE_MEMBER(InterpolantsVSToPS.PerInstanceParams);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if NEEDS_LIGHTMAP_COORDINATE
|
|
|
|
|
TESSELLATION_INTERPOLATE_MEMBER(InterpolantsVSToPS.LightMapCoordinate);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if NUM_TEX_COORD_INTERPOLATORS
|
|
|
|
|
UNROLL
|
|
|
|
|
for(int tc = 0; tc < (NUM_TEX_COORD_INTERPOLATORS+1)/2; ++tc)
|
|
|
|
|
{
|
|
|
|
|
TESSELLATION_INTERPOLATE_MEMBER(InterpolantsVSToPS.TexCoords[tc]);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
return O;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float3x3 VertexFactoryGetTangentToLocalDS(FVertexFactoryInterpolantsVSToDS Interpolants)
|
|
|
|
|
{
|
|
|
|
|
// This duplicates stuff already going on in GetMaterialTessellationParameters(), so
|
|
|
|
|
// maybe the hull shader could leverage that instead?
|
|
|
|
|
half3 TangentToWorld0 = Interpolants.InterpolantsVSToPS.TangentToWorld0.xyz;
|
|
|
|
|
half4 TangentToWorld2 = Interpolants.InterpolantsVSToPS.TangentToWorld2;
|
|
|
|
|
float3x3 TangentToWorld = AssembleTangentToWorld( TangentToWorld0, TangentToWorld2 );
|
|
|
|
|
|
|
|
|
|
return TangentToWorld;
|
|
|
|
|
}
|
|
|
|
|
#endif // #if USING_TESSELLATION
|
|
|
|
|
|
|
|
|
|
#if USE_INSTANCING
|
|
|
|
|
float4 VertexFactoryGetInstanceHitProxyId(FVertexFactoryInput Input, FVertexFactoryIntermediates Intermediates)
|
|
|
|
|
{
|
|
|
|
|
#if !USE_INSTANCING_EMULATED
|
2017-10-13 11:32:28 -04:00
|
|
|
float R = Intermediates.InstanceTransform1.w - 256.0 * GetInstanceSelected(Intermediates);
|
|
|
|
|
float G = Intermediates.InstanceTransform2.w;
|
|
|
|
|
float B = Intermediates.InstanceTransform3.w;
|
2017-07-26 10:00:02 -04:00
|
|
|
#else
|
2017-10-13 11:32:28 -04:00
|
|
|
float R = CPUInstanceTransform[0].w - 256.0 * GetInstanceSelected(Intermediates);
|
2017-07-26 10:00:02 -04:00
|
|
|
float G = CPUInstanceTransform[1].w;
|
|
|
|
|
float B = CPUInstanceTransform[2].w;
|
|
|
|
|
#endif
|
|
|
|
|
return float4(R/255.0, G/255.0, B/255.0, 0);
|
|
|
|
|
}
|
|
|
|
|
#endif // USE_INSTANCING
|
|
|
|
|
|
|
|
|
|
float4 VertexFactoryGetTranslatedPrimitiveVolumeBounds(FVertexFactoryInterpolantsVSToPS Interpolants)
|
|
|
|
|
{
|
2018-12-11 22:25:04 -05:00
|
|
|
float4 ObjectWorldPositionAndRadius = GetPrimitiveData(GetPrimitiveId(Interpolants)).ObjectWorldPositionAndRadius;
|
|
|
|
|
return float4(ObjectWorldPositionAndRadius.xyz + ResolvedView.PreViewTranslation.xyz, ObjectWorldPositionAndRadius.w);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint VertexFactoryGetPrimitiveId(FVertexFactoryInterpolantsVSToPS Interpolants)
|
|
|
|
|
{
|
|
|
|
|
return GetPrimitiveId(Interpolants);
|
2017-07-26 10:00:02 -04:00
|
|
|
}
|