Distant field shadow, how can I avoid it fading close to a surface?

Hey guys,

I am trying distant field shadows vs cascaded as I want soft shadows,
though I am happy with the overall quality and the softness one of the issues I run into is the lack of shadowing on small content.
Some of this is solved by cranking up the value of the assets Resolution scale, though the shadow gets culled/fades when it is close to another surface (see image)

c6481d5ffc4898780b1c400ee6ccddba354a9a63.jpeg

Does anybody know how to get around this?
I looked at console commands to crank it up but had no luck,

Rens

Not sure if this will help, but try playing with “Ray Start Offset Depth Scale” parameter of your Directional light. Also, try setting “Generate Distance field as if TwoSided” under your mesh BuildSettings in Static Mesh Editor. In your case (a leaf) this may help somehow.

Hey Brick thanks for the reply,

Unfortunately the start offset needs to be -0.1 in order to work which creates huge issues,
Using two sided results in a big quad being drawn as shadow,

I’m sure this is just some optimization in the engine or limitation

There’s a hardcoded world space bias applied to avoid accidental self-intersection

DistanceFieldShadowing.usf

// World space offset along the start of the ray to avoid incorrect self-shadowing
float RayStartOffset = 2 + RayStartOffsetDepthScale * SceneDepth;

You can change that 2 to a smaller number.

Although changing that bias to be very small will cause a bunch of other artifacts. What we should really be doing is picking the bias size based on the resolution of the distance field being traced, then it will ‘just work’.

That is exactly what I was hoping to find, Thank you I will start testing right away and create a series of screenshots to figure out what changes.
I can afford a few artifacts or shadows being slightly wrong, but not having any on the ground meshes is brutally noticeable,

What can I do to figure out the number based on the resolution? and are there any limitations surrounding the distance field I can overwrite to increase quality if needed?
(really curious as the documentation does not always cover these in depth changes while I really wish to learn,)

Thanks!

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

// 512Mb
const int32 MaxAtlasDimensionX = 512;
const int32 MaxAtlasDimensionY = 512;
const int32 MaxAtlasDimensionZ = 1024;

Though I have a good understanding of the basics, subtle code changes or with instruction is what I;ll stick to for now : )
(or whatever I can google)

I changed the ray start offset value from 2 to 0.5 for what is roughly needed, but like you predicted it resulted in a lot of unwanted self shadowing errors that on some more than other assets became really visible.
I think some did better than others due to its resolution, though it is near impossible to go higher, (maxing it out at 4 megs per asset, yup) any increase in the resolution number will not result in an better shadow,
guessing that is where im maxing out,

Even if I were to up the memory to 512 for 4.10 manually, I think I have a problem I can not get around which is the resolution needed vs cost paid per asset used…
The memory cost for the resolution is not an instance type of thing is it? Because painting out a brush stroke of mesh scattering I instantly get flickering and culling of various shadows.

Not sure if there is a console command to see the atlas size/memory pool in runtime?

Does the resolution of an object affect the quality of the ray traced ambient occlusion or just the direct shadowing?
Because I most likely need to revert back to cascaded shadows but could keep the ao in place.

No

There are some internal limits on the number of instances that can be handled correctly within a screen tile, due to d3d11 restrictions. This causes flickering when the instance limit is exceeded. Usually objects of that density like grass wouldn’t be performant with DF methods anyway, which is why when you paint instanced foliage you’ll noticed bAffectDistanceFieldLighting is disabled by default.

No, but there’s a log
Allocated %ux%ux%u distance field atlas = %.1fMb

Both, but RTDF shadows are much more sensitive (direct shadowing)

I think I got you derailed on the resolution thing. You can tell if resolution is the problem, because shadows keep getting better as you raise it. If not, then it’s not a resolution problem.

Very useful to know,

You did not derail me from the initial problem, I had some side questions that I figured I would ask while we were on the topic of DF (and its restrictions),
I am reverting back to Cascaded shadows for now and maybe set a transition to DF after 1500 or so.

Thank you for your time!