How to keep self-shadow when disabling CastShadow ?

Hi,

I know this is something not natively supported by the engine at the moment. I’m looking for a way to be able to keep Self-Shadow enabled on one of my skeletal mesh while not having shadow casted on other things (such as the ground). Currently disabling CastShadow in the properties of my SkeletalMeshComponent will get rid of the self-shadows too.

I tried looking into the source and seeing how the boolean “CastShadow” is handled. My course ended inside Source\Runtime\Renderer\Private\ShadowSetup.cpp. Unfortunately I’m stuck to this point. I’m having hard time to figure out what happen here. From what I understand the engine parse every PrimitiveComponent to know what to render. However I don’t see at which point the shadow are handled.

I’m not asking for the full solution of course, but more for some enlightenment about how the engine generate dynamic (self-)shadows.

8989-self_shadow.gif

Yeah that’s a bug. The problem is that the preshadow is no longer created when CastShadow is disabled. The preshadow handles other stuff casting on the movable object. The per-object shadow is what should be disabled when CastShadow is disabled.

Basically allow execution to get to FDeferredShadingSceneRenderer::CreatePerObjectProjectedShadow (by removing previous checks for CastShadow), Then on this line

if (CVarAllowPerObjectShadows.GetValueOnRenderThread() && MaxFadeAlpha > 1.0f / 256.0f)

Add && CastShadow to the condition.

Thanks. To clarify : I’m still on the 4.0.2 version of the engine.

As you suggested, inside ShadowSetup.cpp I changed :

		if (Interaction->HasShadow() 
			// Only render shadows from objects that use static lighting during a reflection capture, since the reflection capture doesn't update at runtime
			&& (!bReflectionCaptureScene || PrimitiveSceneInfo->Proxy->HasStaticLighting())
			&& (bCreateTranslucentObjectShadow || bCreateInsetObjectShadow || bCreateObjectShadowForStationaryLight))
		{
			// Create projected shadow infos
			CreatePerObjectProjectedShadow(Interaction, bCreateTranslucentObjectShadow, bCreateInsetObjectShadow || bCreateObjectShadowForStationaryLight, ViewDependentWholeSceneShadows, PreShadows);
		}

to this :

		if ( (!bReflectionCaptureScene || PrimitiveSceneInfo->Proxy->HasStaticLighting())
			&& (bCreateTranslucentObjectShadow || bCreateInsetObjectShadow || bCreateObjectShadowForStationaryLight))
		{
			// Create projected shadow infos
			CreatePerObjectProjectedShadow(Interaction, bCreateTranslucentObjectShadow, bCreateInsetObjectShadow || bCreateObjectShadowForStationaryLight, ViewDependentWholeSceneShadows, PreShadows);
		}

And this :

		// Only create a shadow from this object if it hasn't completely faded away
		// if (CVarAllowPerObjectShadows.GetValueOnRenderThread() && MaxFadeAlpha > 1.0f / 256.0f)
		if (CVarAllowPerObjectShadows.GetValueOnRenderThread() && MaxFadeAlpha > 1.0f / 256.0f )
		{

to this :

		// Only create a shadow from this object if it hasn't completely faded away
		// if (CVarAllowPerObjectShadows.GetValueOnRenderThread() && MaxFadeAlpha > 1.0f / 256.0f)
		if (CVarAllowPerObjectShadows.GetValueOnRenderThread() && MaxFadeAlpha > 1.0f / 256.0f && Interaction->HasShadow() )
		{

However I didn’t saw any change while toggling CastShadow / CastDynamicShadows on my skeletal mesh. I even tried to enable CastInsetShadows without any luck.

From the few other test I did, it seems that the part of the code after :

		if (CVarAllowPerObjectShadows.GetValueOnRenderThread() && MaxFadeAlpha > 1.0f / 256.0f)

It also handle casting shadow on other objects. Disabling r.Shadow.PerObject (set to 0) remove every shadows. Enabling it cast every shadows.

Is that because the engine handle only one shadow map for every objects ? Meaning there is no way to split self-shadow form casting shadows ?

I’m sorry looks like I completely misunderstood what you were asking the first time. When I was talking about Preshadows, that’s only for shadows from the environment onto the character. The self shadowing of the character AND the character’s shadow onto the ground are handled by the same Per-object shadow, which is applied in a deferred pass to any pixels in the area. That means it is harder to separate what is self-shadowing vs shadowing on other things. It requires knowing what object each pixel belongs to.

It’s still possible to do, just not in the way I was talking about. The high level is to setup a stencil mask on the character’s pixels to mask it out during the Per-object shadow projection pass. This would be done in FProjectedShadowInfo::RenderProjection.

In this branch
// Not a preshadow, mask the projection to any pixels inside the frustum.
else
{

Now add some code that writes 0 to stencil for the subject meshes of the shadow. This is almost like the code in if (bPreShadow), except we want to write 0 (mask out) to stencil instead of 1, and we want to draw the shadow’s subject meshes instead of receivers.

Sorry I don’t have the actual code, but my version at latest would be different than yours anyway.