DeformerGraph Error / Tutorials?

Anyone have a tutorial on making your own Deformer Graph, and programming the Custom Kernel Computation’s Shader Source? What functions can we use in it, etc. And what is the DefaultDeformerGraph doing - will a Deformer Graph work if I just output positions, not worrying about tangents?

I just want to add the deltas together, to make the ML Deformer work with morph targets additively…
image
WriteOutputPosition( add( ReadInitPosition(Index), ReadDelta1(Index), ReadDelta2(Index) ) );

But I’m getting this error
image
syntax error: unexpected token 'Add' (line 23) *OptimusNode_CustomComputeKernel*

Well I haven’t found any info yet but here’s what was wrong:

  • The error was because there was a space in my Kernel Name. Can’t have spaces in any names.

  • add() doesn’t seem to exist, just use +. Maybe add() can be used if you #include “/Engine/Private/FastMath.ush”

  • I also forgot to pass in the Index to WriteOutputPosition

WriteOutputPosition( Index, ReadInitPosition(Index) + ReadDelta1(Index) + ReadDelta2(Index) );

(By the way, when it throws an error about an unexpected ‘)’, that usually means one of the input/output bindings isn’t being set, or something along those lines.)

After fixing those things, it successfully applied the ML Deformer but the mesh didn’t move with the bones. So instead I stitched together the built-in DefaultML_DeformerGraph and DG_LinearBlendSkinning_Morph_Cloth, and it works!

I don’t know if it’s the proper order to apply the deformations in, but here’s what I chose:
Linear skinning → ML Deformer → Morph Target → Cloth

Here’s the working thing:

LBS_PreMLDelta:

if (Index >= ReadNumVertices()) return;

float3 LocalPosition = ReadPosition(Index);
float4 LocalTangentX = ReadTangentX(Index);
float4 LocalTangentZ = ReadTangentZ(Index);
float3 PositionDelta = ReadPositionDelta(Index);

LocalPosition += PositionDelta;

float3x4 BlendMatrix = ReadBindMatrix(Index);

float3 SkinnedPosition = mul(BlendMatrix, float4(LocalPosition, 1));
float4 SkinnedTangentZ = float4(normalize(mul((float3x3)BlendMatrix, LocalTangentZ.xyz)), LocalTangentZ.w);

WriteOutPosition(Index, SkinnedPosition);
WriteOutTangentZ(Index, SkinnedTangentZ);

LinearBlendSkin_Morph_Cloth:

if (Index >= ReadNumVertices()) return;

float3 LocalPosition = ReadPosition(Index);
float4 LocalTangentX = ReadTangentX(Index);
float4 LocalTangentZ = ReadTangentZ(Index);

float3 DeltaPosition = ReadDeltaPosition(Index);
float3 DeltaTangentZ = ReadDeltaNormal(Index);

float3 MorphPosition = LocalPosition + DeltaPosition;
float3 MorphTangentZ = LocalTangentZ.xyz + DeltaTangentZ;

float3 ClothWeight = ReadClothWeight(Index);
float3 ClothPosition = ReadClothPosition(Index);
float3 ClothTangentX = ReadClothTangentX(Index);
float3 ClothTangentZ = ReadClothTangentZ(Index);

//float3x4 BlendMatrix = ReadBindMatrix(Index);

//float3 SkinnedPosition = mul(BlendMatrix, float4(MorphPosition, 1));
//float4 SkinnedTangentX = float4(normalize(mul((float3x3)BlendMatrix, LocalTangentX.xyz)), LocalTangentX.w);
//float4 SkinnedTangentZ = float4(normalize(mul((float3x3)BlendMatrix, MorphTangentZ.xyz)), LocalTangentZ.w);

float3 LocalClothPosition = mul(float4(ClothPosition, 1), ReadClothToLocal()).xyz;
float3 FinalPosition = lerp(MorphPosition, LocalClothPosition.xyz, ClothWeight);

float4 FinalTangentX = float4(lerp(LocalTangentX.xyz, ClothTangentX, ClothWeight), LocalTangentX.w);
float4 FinalTangentZ = float4(lerp(MorphTangentZ.xyz, ClothTangentZ, ClothWeight), LocalTangentX.w);

WriteOutPosition(Index, FinalPosition);
//WriteOutTangentX(Index, FinalTangentX);
WriteOutTangentZ(Index, FinalTangentZ);

Btw to get this to work, delete the bind matrix from the LinearBlendSkin_Morph_Cloth node’s input bindings

The other two nodes about recalculating normals can stay the same

1 Like