Indirect Instancing(VHFM) shadows issue

Hello,
i am trying to get shadows to work with indirect instancing. i used a code snippet i found on the shadeup plugin website: Bare-bones single triangle indirect instancing in UE5 | Indirect Instancing | Shadeup
i draw a simple triangle just to test if the shadows work.


the problem is, that the drawn triangle is drawn but ignored by the shadow calculation.

the plugin i use, is a reduced version of the virtual height field mesh. i found this in the code:

// Can’t add new work while bInFrame.
// In UE5 we need to AddWork()/SubmitWork() in two phases: InitViews() and InitViewsAfterPrepass()
// The main renderer hooks for that don’t exist in UE5.0 and are only added in UE5.1
// That means that for UE5.0 we always hit this for shadow drawing and shadows will not be rendered.
// Not earlying out here can lead to crashes from buffers being released too soon.

since i use ue version 5.4 i thought i can just remove those checks, but as you can see there are still no shadows…

so the question is, what is missing or how can i solve this issue?
i searched in the source of the engine since other components use indirect instancing too. but i don’t see any difference in the engine and the plugin. i compared the niagara plugin and the water component. but the water component does not use shadows i guess.

I think the issue is the vertex factory. i miss something and i can’t figure out what is missing.

// Copyright Epic Games, Inc. All Rights Reserved.
// Adapted from the VirtualHeightfieldMesh plugin

#include "/Engine/Private/VertexFactoryCommon.ush"
#include "/Engine/Private/VirtualTextureCommon.ush"
#include "ExampleIndirectInstancing.ush"

StructuredBuffer<QuadRenderInstance> InstanceBuffer;
float3 LodViewOrigin;
// float4 LodDistances;

/** Per-vertex inputs. No vertex buffers are bound. */
struct FVertexFactoryInput
{
	uint InstanceId : SV_InstanceID;
	uint VertexId : SV_VertexID;
};

/** Cached intermediates that would otherwise have to be computed multiple times. Avoids relying on the compiler to optimize out redundant operations. */
struct FVertexFactoryIntermediates
{
	float2 LocalUV;
	float3 LocalPos;
	float3 WorldNormal;
	/** Cached primitive and instance data */
	FSceneDataIntermediates SceneData; 
};

FPrimitiveSceneData GetPrimitiveData(FVertexFactoryIntermediates Intermediates)
{
	return Intermediates.SceneData.Primitive;
}

/** Attributes to interpolate from the vertex shader to the pixel shader. */
struct FVertexFactoryInterpolantsVSToPS
{
#if NUM_TEX_COORD_INTERPOLATORS
	float4 TexCoords[(NUM_TEX_COORD_INTERPOLATORS + 1) / 2] : TEXCOORD0;
#endif
#if INSTANCED_STEREO
	nointerpolation uint EyeIndex : PACKED_EYE_INDEX;
#endif
};

/** Compute the intermediates for a given vertex. */
FVertexFactoryIntermediates GetVertexFactoryIntermediates(FVertexFactoryInput Input)
{
	FVertexFactoryIntermediates Intermediates;
	Intermediates.SceneData = VF_GPUSCENE_GET_INTERMEDIATES(Input);

	const QuadRenderInstance Item = InstanceBuffer[Input.InstanceId];
	uint2 VertexCoord = uint2(Input.VertexId % 2, Input.VertexId / 2);
	const uint2 Pos = VertexCoord * 1000.f;
	const uint Level = 0; //UnpackLevel(Item);
	
	
	const float3 LocalUVTransform = float3(0.0f, 0.0f, 0.0f);

	float2 LocalUV = (float2)VertexCoord / (float)(2 - 1);

	// Calculate vertex UV details before morphing
	float2 XY = ((float2)Pos + LocalUV) * (float)(1u << Level);
	float2 NormalizedPos = (XY * 1.f);
	float SampleLevel = Level;

	// Position in space of virtual texture volume
	// Intermediates.VTPos = float3(0, 0, 0);

	// Position in local space
	Intermediates.LocalPos = float3(Pos, Input.InstanceId * 100.f);//mul(float4(Intermediates.VTPos, 1), VHM.VirtualHeightfieldToLocal).xyz;
	Intermediates.LocalPos /= ((float) (Level + 1));
	
	Intermediates.LocalUV = NormalizedPos;

	Intermediates.WorldNormal = float3(0, 0, 1);

	return Intermediates;
}

/** 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.SceneData = Intermediates.SceneData;
	Result.WorldPosition = WorldPosition;

	// needs fixing!
	// Result.TangentToWorld = mul(TangentToLocal, (float3x3)VHM.VirtualHeightfieldToWorld);
	Result.TangentToWorld[2] = Intermediates.WorldNormal;

	Result.PreSkinnedPosition = WorldPosition;// Intermediates.WorldPosPreDisplacement.xyz;
	Result.PreSkinnedNormal = float3(0, 0, 1);

#if NUM_MATERIAL_TEXCOORDS_VERTEX
	UNROLL
	for (int CoordinateIndex = 0; CoordinateIndex < NUM_MATERIAL_TEXCOORDS_VERTEX; CoordinateIndex++)
	{
		Result.TexCoords[CoordinateIndex] = Intermediates.LocalUV;
	}
#endif  //NUM_MATERIAL_TEXCOORDS_VERTEX

	return Result;
}

/** Get ID in GPU Scene. We don't implement support because we create/consume our own instancing buffer. */
uint GetPrimitiveId(FVertexFactoryInterpolantsVSToPS Interpolants)
{
	return 0;
}

/** Get ID in the GPU Scene. */
uint VertexFactoryGetPrimitiveId(FVertexFactoryInterpolantsVSToPS Interpolants)
{
	return GetPrimitiveId(Interpolants);
}

/** Computes the world space position of this vertex. */
float4 VertexFactoryGetWorldPosition(FVertexFactoryInput Input, FVertexFactoryIntermediates Intermediates)
{
    FDFMatrix LocalToWorld = GetPrimitiveData(Intermediates).LocalToWorld;
    FDFVector3 WorldPosition = DFMultiply(Intermediates.LocalPos, LocalToWorld);
    float3 TranslatedWorldPosition = DFHackToFloat(DFAdd(WorldPosition, ResolvedView.PreViewTranslation));
    return float4(TranslatedWorldPosition, 1.0f);
}

/** Computes the world space position of this vertex. */
float4 VertexFactoryGetRasterizedWorldPosition(FVertexFactoryInput Input, FVertexFactoryIntermediates Intermediates, float4 InWorldPosition)
{
	return InWorldPosition;
}

/** Computes the world space position used by vertex lighting for this vertex. */
float3 VertexFactoryGetPositionForVertexLighting(FVertexFactoryInput Input, FVertexFactoryIntermediates Intermediates, float3 TranslatedWorldPosition)
{
	return TranslatedWorldPosition;
}

/** Computes the world space position of this vertex last frame. */
float4 VertexFactoryGetPreviousWorldPosition(FVertexFactoryInput Input, FVertexFactoryIntermediates Intermediates)
{
    return DFTransformLocalToTranslatedWorld(Intermediates.LocalPos, GetPrimitiveData(Intermediates).PreviousLocalToWorld, ResolvedView.PrevPreViewTranslation);
}

/** Computes the world space normal of this vertex. */
float3 VertexFactoryGetWorldNormal(FVertexFactoryInput Input, FVertexFactoryIntermediates Intermediates)
{
	return Intermediates.WorldNormal;
}

/** Get the 3x3 tangent basis vectors for this vertex factory. This vertex factory will calculate the binormal on-the-fly. */
half3x3 VertexFactoryGetTangentToLocal(FVertexFactoryInput Input, FVertexFactoryIntermediates Intermediates)
{
	return half3x3(1, 0, 0, 0, 1, 0, 0, 0, 1);
}

/** Get the translated bounding sphere for this primitive. */
float4 VertexFactoryGetTranslatedPrimitiveVolumeBounds(FVertexFactoryInterpolantsVSToPS Interpolants)
{
    FPrimitiveSceneData PrimitiveData = GetPrimitiveData(GetPrimitiveId(Interpolants));
    return float4(DFFastToTranslatedWorld(PrimitiveData.ObjectWorldPosition, ResolvedView.PreViewTranslation), PrimitiveData.ObjectRadius);
}

#if NUM_TEX_COORD_INTERPOLATORS

void SetUV(inout FVertexFactoryInterpolantsVSToPS Interpolants, uint UVIndex, float2 InValue)
{
	FLATTEN
	if (UVIndex % 2)
	{
		Interpolants.TexCoords[UVIndex / 2].zw = InValue;
	}
	else
	{
		Interpolants.TexCoords[UVIndex / 2].xy = InValue;
	}
}

float2 GetUV(FVertexFactoryInterpolantsVSToPS Interpolants, uint UVIndex)
{
	float4 UVVector = Interpolants.TexCoords[UVIndex / 2];
	return UVIndex % 2 ? UVVector.zw : UVVector.xy;
}

#endif

/** Constructs values that need to be interpolated from the vertex shader to the pixel shader. */
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]);
	}
#endif

	return Interpolants;
}

/** 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 (uint CoordinateIndex = 0; CoordinateIndex < NUM_TEX_COORD_INTERPOLATORS; CoordinateIndex++)
	{
		Result.TexCoords[CoordinateIndex] = GetUV(Interpolants, CoordinateIndex);
	}
#endif	//NUM_MATERIAL_TEXCOORDS

	Result.TwoSidedSign = 0;
	Result.PrimitiveId = GetPrimitiveId(Interpolants);

	return Result;
}

#include "/Engine/Private/VertexFactoryDefaultInterface.ush"