Large 3d gridmap vs. performance

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Macryc

Hi All-
I’ve built a system that allows me to quickly build levels of any size / complexity using 3d gridmaps. My player character is followed by the camera from a high-angle view.
I’ve been testing this setup with different cell types, objects, lights, vfx etc etc. but never really got a map to a size that I’m intending for the actual game (you know, I was just testing…). That is, until now. With 80% of my baseline system being ready, I thought I’d go ahead and build an actual full map.
The game is be a dungeon-crawler-type game with point-and-click movement mechanic (kinematic bodies moving and sliding along paths). So I built a decent-size map (not anything daunting - it’s not an open world or anything), instanced a bunch of interactive stuff on it that’s required for quests etc… and performance dropped so bad it’s barely playable… I literally cannot rotate the camera without FPS dropping to 5-10 (no such problems with smaller maps I used for testing).

Question:
My in-game cam view range is only 70 units so not far - everything beyond is clipped off (and obscured by fog). Yet, performance suffers so bad with a larger map as if the camera was trying to render absolutely everything on the map? Is that possible?
How do you deal with large maps in Godot?

PS. Yes I’m using a s#itty old GPU (AMD Firepro d300) but I’m kinda aiming for old PCs to be able to run this thing… Could this be the GPU?

I know that Godot still has to do the effort of culling things outside of camera clip, so even if they don’t end up rendered, they still cost CPU power.

Hard to check what other problem there would be here. It may depend on what you do in your project. Did you check the profiler to see which parts of the engine are taking the most time?
If the profiler doesn’t tell enough information, we could get more insight by profiling the engine directly with a C++ profiler (because it’s open source), unfortunately additions such as Tracy were rejected so far so to do this we need to do it by hand.

Maybe you could also provide a test scene that shows the performance drop.

Zylann | 2020-09-08 12:56

I must admit that, stupidly, I wasn’t aware Godot came with a profiler. I’ll look into that and follow up.

You mentioned that the culling beyond camera clip is still expensive even when nothing is rendered. I was wondering… If I hid my instanced meshes (set them to not be visible) beyond a certain distance, would that have any impact on rendering? I mean, if a node is hidden, is it still drawn?

Macryc | 2020-09-08 13:19

You mentioned that the culling beyond camera clip is still expensive even when nothing is rendered

That’s not exactly what happens.
Things that exist in the world but are not being rendered still take a small CPU hit because Godot had to calculate wether or not to render them in the first place. That cost exists for any mesh instance, visible or not.

If I hid my instanced meshes (set them to not be visible) beyond a certain distance, would that have any impact on rendering?

Probably not. They are still present within the culling data structures. However that will be an issue for you only if you really have a lot of them. Don’t change all visible switches just because of this until you are certain that it’s a problem for you.
I gained some FPS in my voxel engine by completely removing instances from the world when not visible, instead of setting visible=false, because I deal with hundreds, or sometimes thousands of them, and Godot takes a lot of time just to cull everything.

I mean, if a node is hidden, is it still drawn?

No. But again, “not being drawn” is not the cause here.

Your problem might be something else though. Hard to say without a test scene.

Zylann | 2020-09-08 17:57

in your voxel engine, how do you instance/free the voxels dynamically? Are you going this by distance from camera? I was thinking of something similar but I’m struggling for a method that would instance nodes on cell items (i’m basically instancing various scenes based on grid cell types underneath, eg a grass cell will receive an instance of a random bush/shrub/etc atop) when the camera is close, and free them when the camera moves away, and then instance again when it gets closer again and so on…

Macryc | 2020-09-08 19:26

in your voxel engine, how do you instance/free the voxels dynamically?

I don’t. When I say “hundreds”, I mean chunks. Voxels are not stored as objects.

I was thinking of something similar

Until we know what the source of your lag is, it may be too early to start doing something like that.

Zylann | 2020-09-08 19:30

OK, I’ve built a function that instances and frees meshes based on distance from camera and clearly that wasn’t the problem. It did help a bit (I got the FPS from a lousy 38 up to 45) but that’s still way below expectations.
I’ve run the profiler to check and the largest load by far is on ‘Physics Frame’ and ‘Idle Time’. I’m not sure what I can do to alleviate that?

Macryc | 2020-09-09 07:07

[closing comment]

After some more testing, the issue turned out to be a mix of expensive environment settings, the count of meshes on the map and the sheer stretch of the gridmap itself.

I’ve added a GPU selector up front which adjusts the environment settings. It also adjusts the render distance for instanced resources (ie, instances them only when they’re close enough to be seen, and frees them whey they’re beyond view).

This has solved the problem. On lowest GPU settings the look is still kinda OK (no DOF, no ssao, no nothing, just fog) and the game plays smooth as butter even on an ancient 2gb gpu like mine. I tested on my son’s rtx2080s and it’s 120FPS even with all environment settings cranked up to the max. I guess I was overthinking it…

Anyway, appreciate your comments Zylann.

Macryc | 2020-09-09 09:07