Detect if actor is casting a shadow

There are several actors which do complex work that only needs to be done when they have an effect on the screen. We can detect if an actor is in the camera view frustum and disable it when it’s not.

However, an off-screen actor may be in the view frustum of a shadow casting light and the shadows on the screen should reflect the actor’s state.

Is there a way to detect if an actor is contributing to on-screen shadows?

Tha’ts a good question.. I don’t know of a way to do that directly, however, ultimately the shadow is just a projection from an angle. Discarding occlusion & discarding surface checks, if you have a limited amount of shadow-casting lights, you could simply draw a trapeze with the top and bottom point of your actor, that represents the “path” of the shadow from the actor to potential surfaces (once per shadow casting light), and see if any of these “projections” intersects the view frustrum.

I would also take a step back and worry about this whole idea of manually culling actors outside the view frustrum. This should be something that’s handled by the engine already. Everything you need may well be done by the engine already, with only CVars (or actor variables) to adjust to your liking.

The culling is done for rendering, yes but the actors are still present in the world (between begin and end play calls). What they do every frame they exist is a manual concern as far as I can tell.

Looking more into it there is WasRecentlyRendered(float Tolerance) for actors and components which returns true if the object was rendered for either the view or shadows within the specified time.

In FPrimitiveSceneDataInfo there are two member variabled:

	/**
	 * The value of WorldSettings->TimeSeconds for the frame when this component was last rendered.  This is written
	 * from the render thread, which is up to a frame behind the game thread, so you should allow this time to
	 * be at least a frame behind the game thread's world time before you consider the actor non-visible.
	 */
	mutable float LastRenderTime = -1000.0f;

	/** Same as LastRenderTime but only updated if the component is on screen. Used by the texture streamer. */
	mutable float LastRenderTimeOnScreen = -1000.0f;

Shadow calls update only LastRenderTime and render calls update both LastRenderTime and LastRenderTimeOnScreen.

Note that this gives the time since the primitive was in the frustums (or for ray tracing) but does not specify whether the object is visible or occluded (which is fine for the current issue). The render thread is also behind the game thread (always? sometimes?) if that matters for anyone.

Not sure how to make this into an event trigger as you would have to poll the data when you need it.

1 Like