How to Disable Frustum Culling for an Actor or Component?

Hello!

I know I can override the UPrimitiveComponent::CalcBounds() call and return a ginormous FBoxSphereBounds object, and that seems to do the trick. But I was wondering if there is a nicer way to simply have an actor/component never be culled if it falls outside the view frustum or even max render distance. So far I see that the SceneVisibility.h’s FrustumCull() iterates through all things in FViewInfo::PrimitiveVisibilityMap and checks if it is “Visibile” but not seeing some way to bypass that test or if it is possible to not have my primitive in that array (PrimitiveVisibilityMap) or if that is even possible.

Thanks!

2 Likes

Just out of curiosity, why on earth would you need to do this?

2 Likes

I have created a scene component that renders infinite water in all directions as necessary. However if the view point ends up far enough away that its frustum never intersects with the water component’s defined bounds, it gets culled. I can set the water component’s bounding volume to be huge and that essentially prevents it from ever being culled, but I was curious if there was some other way to keep that component around at all times without this sort of “hacky” solution.

2 Likes

I see this topic is old but,
I am interested if there is a way to disable culling too. If there are a ton of simple geometries the computation involved with culling is far greater than what is required to render all of the simple objects.

1 Like

Just wanted to bump this tread up. Encountered problem where sequencer doesn’t update SkeletalMesh master bounds for slave components properly under some circumstances and culling those components out.

1 Like

Yeah, How to I turn this stuff off bothering me right now.

1 Like

Hi lol, im also interested in disabling fustrum culling. There are som situations where it is necessary. If im making a videogame where i need to hide from an enemy, and i have a reflective wall on my right, i need to see if that enemy aproaches (because he will reflect in the wall). But since the camera is not pointing at that actor, the enemy is never going to be rendered and its never going to work. Imagine the same thing but instead of a character is a static mesh, that moves or whatever. I mean, how in hell do people things like these?. Ive been trying to find a workaround about camera fustrum culling for days. I come from unity and in there, we dont have these problems at all. There are ways to activate or disable it in a easy way. How the heck do we disable camera culling in unreal engine?? im trying to switch from unity to ue but at this rate and with so many “problems” im finding in the way, im afraid i will go back to unity. People ask other people why to chose Unity over UE, this is one of the great examples why.

Anyone? i guess its time to go back to unity then. Its not worthy all the trouble.

5 Likes

Time for the yearly bump I guess. Also interested.

2 Likes

+1

+1

+1

+1

+1

Custom culling rules can be set in C++:

There’s this renderer module method that makes the renderer to use the specified custom culling rules:

void IRendererModule::RegisterCustomCullingImpl(ICustomCulling* impl) = 0;

you must give it an object that inherits from this interface (a culling query factory):

class ICustomCulling
{
public:
	virtual ICustomVisibilityQuery* CreateQuery (const FSceneView& View) = 0;
};

The CreateQuery()'s returned object will be used to perform the actual custom visibility check, it must be inherited from ICustomVisibilityQuery interface:

class ICustomVisibilityQuery: public IRefCountedObject
{
public:
	/* prepares the query for visibility tests */
	virtual bool Prepare() = 0;

	/* test primitive visiblity */
	virtual bool IsVisible(int32 VisibilityId, const FBoxSphereBounds& Bounds) = 0;

	/* return true if we can call IsVisible from a ParallelFor */
	virtual bool IsThreadsafe()
	{
		return false;
	}
};

If all you need a “never culled object” i think Prepare() can be left empty and IsThreadsafe() can return true (to make the culling run in multiple threads which is faster).

1 Like

Woww… Somebody tried to answered this question after 8 years !!!

Constantly bumping this thread from few days for searching the same thing in the question.

Anyways,
Can we define this piece of code for each actor? or will this affect the entire project?
I checked the RendererInterfact.h (Where I can see ICustomVisibilityQuery class), but I am not sure how I can set this for the each actor.

Thank you
-Piyush

1 Like

Im not very c++ savy in unreal. Does that apply to all actors? Or can be made in such a way that it only applies to specific actors?

Bumpity bump? BUMP :smiley:

I did look into the culling code a bit further.

Looks like CustomVisibilityQuery has no ability to prevent the standard frustum check from culling primitives - it can only cull additional primitives, here’s the relevant code from SceneVisibility.h:

// IF DISTANCE CULLED
if (bDistanceCulled ||
// OR IF CUSTOM CULLING QUERY SAYS ITS CULLED
(UseCustomCulling && !View.CustomVisibilityQuery->IsVisible(VisibilityId, FBoxSphereBounds(Bounds.BoxSphereBounds.Origin, Bounds.BoxSphereBounds.BoxExtent, Bounds.BoxSphereBounds.SphereRadius))) ||
// OR IF BOUNDING SPHERE - CAMERA FRUSTUM CULLING SAYS ITS CULLED
(bAlsoUseSphereTest && View.ViewFrustum.IntersectSphere(Bounds.BoxSphereBounds.Origin, Bounds.BoxSphereBounds.SphereRadius) == false) ||
// OR IF BOUNDING BOX - CAMERA FRUSTUM CULLING SAYS ITS CULLED
(bUseFastIntersect ? IntersectBox8Plane(Bounds.BoxSphereBounds.Origin, Bounds.BoxSphereBounds.BoxExtent, PermutedPlanePtr) : View.ViewFrustum.IntersectBox(Bounds.BoxSphereBounds.Origin, Bounds.BoxSphereBounds.BoxExtent)) == false)
{
	// ITS CULLED
}
else
{
	// ITS NOT CULLED
}

So, it looks like there is no way to disable the culling without modifying the engine source code after all.

This logic can be rewritten in a way that custom query will override the staddard checks (“if the custom query says its not culled then do not perform other checks and mark this primitive visible”).

1 Like

As for the per-actor check - culling code is rather low level, it knows nothing about actor system, and operates only on proxy primitive data that is passed to renderer from game code.

ICustomVisibilityQuery::IsVisible(int32 VisibilityId, const FBoxSphereBounds& Bounds)

There is this VisibilityId parameter that can be used inside the custom check.
It is filled from UPrimitiveComponent::VisibilityId property (not exposed to blueprints by default). By setting it to some “special” value you can find your primitive inside the ICustomVisibilityQuery::IsVisible() check.

This property is used by static lightning system though, so changing it naively might not work - an experiment is needed.

1 Like

The other option is to increase the bounds of the mesh to 99999 and that will make it visible everywhere.
Though i dont know if this will cause some unknown issue.
From my tests it seems its working properly except for a major issue that could break my game.
That is when using Get instances with Sphere Overlap.
It will not work because it gets the 99999 bounds.
The solution for that is to copy the function Get Instances From Overlap Sphere, and change the bounds there.
That way there is no frustum culling for the specific actor.
Could this cause any other problem that we dont know of?