Is there a cheap way to check if a location is visible/occluded?

Hi!

I’m wondering if there’s a computationally cheap way to find out if a point (or better: volume) within the camera’s frustum is visible to the player or occluded by an obstacle. I am aware that actors track the last time they’ve been rendered, so if an actor were already there I could use this, but I’d like to determine where I can spawn actors without the player seeing them pop out of thin air, so I need the information for an empty volume…

Thanks in advance,

I suppose you could use traces. Suppose you have a bounding volume (a rectangle for simplicity), you could trace from each of its corners to the camera location and if all of the traces hit something it’s safe to assume the box is occluded from the camera’s view.

See documentation on traces:

Thanks, that’s what I’m likely going to do. It’s not a guarantee though, as there might be situations where all bounding box edges are occluded, but some volume in between is not (think: looking along a corridor, and spawning something in the room at its end - the left side of the bounding box might be hidden by the left corridor wall, right side by the right corridor wall, but the center would still be visible…).

I’m also thinking about doing a few shape traces to emulate the perspective of the camera (making the box of the trace bigger and bigger the farther away from the camera it is).

1 Like

I’m thinking it might be worth exploring further your original idea of looking at whether an actor’s been rendered yet or not.

Maybe you could create an invisible minimal actor that you spawn at the relevant locations and then check whether they’ve been rendered or not, and based on that you can spawn the real actor if conditions are met.

I’m not sure whether this approach would work for invisible actors though.
Maybe you could trick the engine by adding a one-sided plane (facing away from the player camera) to the minimal actor.

We finally managed to get to the point where this became relevant, and our final implementation turned out to be a combination of both approaches. First we do a line trace from the spawn position to all player cameras. If the line trace gets through, we know that the location is visible. If not, we place an actor with a completely cutout material (meaning: invisible) and wait some time. After that we use the actor’s WasRecentlyRendered() method to check if it has been rendered. If it hasn’t, we spawn the real actor in its place. As the WasRecentlyRendered() check only works locally, and I didn’t have the time to set up a replicated version of it, we only do this for the server. For clients we chose to instead just go with several line traces (edges, center) and call it a day. So, with enough bad luck, a spawning actor might be visible on the client, but on the server we are pretty certain that the spawn location is invisible.

There would be an even better option, but I sadly didn’t have the time to figure out how to use it. In SceneVisibility.h there’s a struct named FOcclusionBounds, which should offer all that’s required to check the occlusion state of an axis aligned bounding box, and further down the file one can see how it is used. Sadly, this all is in private engine files, and even worse: the commands used have to be run in the render thread (and this is where I gave up and decided to just place a transparent actor instead).

1 Like