Are you looking for actual code advice? Because it’s gonna get technical =)
float4 UVScaleAndVolumeScale = LoadObjectUVScale(ObjectIndex, bGeneratedAsTwoSided);
float WorldToVolumeScale = 1.0f / UVScaleAndVolumeScale.w;
These, together with the object’s DF resolution are needed to compute the size of a texel in world space. Then the original RayStartOffset bias can be removed, and replaced with a per-object bias coming from the size of the DF texel.
There are a number of limitations to quality in DistanceFieldShadowingShared.usf where the ray marching kernel lies. For example
uint MaxSteps = 64;
Most steps allowed through a single object before we quit and call it shadowed. This is a limiting factor toward soft
float MinStepSize = 1.0f / (4 * MaxSteps);
Smallest step size allowed. This is a limiting factor toward soft penumbras.
If you have a lot of meshes with high DF resolution, you can hit the max atlas size. In previous builds this was 256Mb and fairly easy to hit in a production scene. In 4.11 it’s been raised to 512mb, DistanceFieldAtlas.cpp
const int32 MaxAtlasDimensionX = 512;
const int32 MaxAtlasDimensionY = 512;
const int32 MaxAtlasDimensionZ = 1024;