Game Map/Level Polygon count

Started by
12 comments, last by vanka78bg 8 years, 1 month ago

In an attempt to save level design time and final asset storage requirements I started to work in some kind of semi procedural system. I made a base tileable wall for a cave/mine like dungeon, then I apply a noise algorithm to displace vertices and make very unlikely for the player to encounter the same pattern when looking at the walls.

I originally wanted to apply the displacement in a vertex shader, but I still learning to code them, so for now It's all software, the problem is that doing It by software is too slow. So I went back to the 3D editor (Blender) and applied the displacement there then exported the whole cave, divided in parts to optimize culling, in a format understood by the game engine, so I can see something in the game window for now. The problem is that the result has a lot of polygons.

All information I could find about polycount is about the characters. But I'm not interested in the characters, this is a real time strategy game, the characters won't ever by near the camera and they are all low poly. I'm interested in typical polycounts for the game maps/levels.

My 4th generation i3 with NVidia GPU seems to handle my level correctly so far, but I'm trying to support as old hardware as possible. Core 2, if possible P IV, should be enough for this game as I'm betting for the gameplay not the graphics.

Advertisement

There are many variables. So some questions:

What is the poly count and vertex count?

How many draw calls are you using?

How many state changes do you have?

Modern cards can have enormous polygon count and vertex counts compared to past years, but you need to keep the draw calls and state changes to a reasonable number. Two million, three million, five million polygons and verts, modern cards can handle that if you've done everything else right.

Anything over a few hundred draw calls, 300-500 or so, and you're going to start having performance problems. The exact number varies depending on the calls and the data transfers involved.

You can also have a similar number of state changes, although those also vary somewhat because some state changes are more costly to perform than others.

If you've got a large but stable mesh for the nearby cave/mine world that you can keep on card and draw with a single call, it is probably not an issue. Even a six-figure vertex count for the level model isn't a problem on modern cards if you can hit is all with a single draw call.

to reinforce frobs statement, for the current time being (pre DX12/Vulkan), Drawcalls will be your bottleneck, not the polygon count.

It is pretty amazing what modern cards can do when it comes to poly count, and game developers are only moving slowly to catch up with their games (for many reasons, one of them being that "modern cards" are actually less widely used than we would like to believe).

Add to that the many advanced culling algorithms that are used by modern engines to further reduce the amount of polygons that will be rendered by the GPU, and the problem of having many polygons in the same level, BUT NOT VISIBLE AT THE SAME TIME is becoming even less of an issue.

So basically, if your polygon DENSITY is not too high, the total amount of polygons in a level is not a performance issue for the CPU or GPU (maybe memory, maybe space on disk, maybe load times... but not rendering)... as long as your culling method is working as intended and you only render what is visible (without choking the system with a too aggressive culling... that can actually decrease performance, if you do too many culling checks without much geometry being culled).

But Drawcalls can choke your system still... as long as your level is built up of too many separate meshes that are NOT combined into a single mesh with a single texture atlas, NOT batched by some mechanism and NOT instanced, each additional mesh will cause additional draw calls. Which is something modern cards still do not handle all that well (its something like a context switch on the CPU AFAIK, thus the old values will be wiped, and new values will be filled into registers and all. Compared to adding some more vertices and polygons to an object that is already rendered at full speed on the GPU, that is way way way more expensive).

There are many ways to reduce the amount of draw calls, ESPECIALLY with something static as level geometry. If you are using Unity, Unity does dynamic batching (no idea if this is now included in the free version). Basically Unity will take all the geometry marked as static and combine it into a single draw call.

You can do the same if you combine all the meshes that compromise your level into a single object in an external 3D App and create a Texture Atlas. This should make the object being sent to the GPU in a single draw call.

And then there is DX12 which should do some kind of builtin batching automatically. I didn't read the specifics, but there where claims that it could create quite large batches out of non-instanced meshes.

Of course, the BIG bottleneck about draw calls is not on the GPU, but the CPU. A draw call is basically the CPU preparing the information needed for the GPU, and then this information being sent to the GPU and the GPU switching to rendering a new object to the screen.

From what I have seen, these draw calls tend to choke the CPU way before the GPU gives in. Depends on your CPU and GPU really, but with a top end i7 2600k and top end Nvidia GTX 680 from 2013 the result was that at least in my case, a prototype running in Unity with too many draw calls, the CPU was choking WAY before the GPU. This was with quite a lot of physics going on, and game logic and other things also running in the main thread.

And as with many other game engines, Unity is still not properly mutli-threaded (Physics AFAIK have their own thread, but the main thread is still doing 80+% of the work).

You COULD get away with more draw calls if you would be able to move the render thread to a different core. Maybe you could split the render thread into multiple threads (as Unity seems to be doing right now with Unity 5.3)... the fact still remains that pre DX12, draw calls are severly limited because they tend to choke the CPU.

Best thing is to reduce draw calls.

I have little control on draw calls as I'm using a third party engine. It is open source but I'm not confidence enough to try to optimize it. So the best I can do to reduce draw calls is to partition the mine level massive mesh in smaller chunks to give the engine the chance to cull parts of it. That's what I'm doing.

Decision about the size of these chunks isn't based on any study, I'm just testing random things. If 1.0 in the mesh is 1 meter then I'm using a 10 meters square chunks. The whole mine, right now, is a rectangle of 432x323 meters.

Every 2 meters, a single side wall is 2017 triangles. I don't know about the ground, It's just a plane for now but the plan is to add some heights later.

To give you the total mine/cave polygon count I need to rearm everything first and look at the total triangle count, I will update this post later with that information. The engine supports a debug dialog that shows the draw calls and other debug info, I will take a screenshot of that dialog.

For now, this is a screenshot of the base wall:

image.png image.png

image.png

Left: the base wall asset. Other mines/caves will use a different one, but this is the one used nearly everywhere in this specific game level.

Right: the same asset with the displacement applied, backed up by a noise function.

Bottom: a corridor side formed by repeating the base wall, the noise function hides the fact that It's always the same wall. There are some seams distinguishable in that screenshot but that is because Blender doesn't offer control on the normals, the seams will disappear in the game engine.

No textures so far.

What engine? Just curious.

-potential energy is easily made kinetic-

What engine? Just curious.

JMonkey. You code in Java.

I'm pretty sure I know someone who was able to get 1 million polygons running on a HD 4400 without a lot of passes. Seeing as that you are a single person like him, and not a team with optimizers, and also seem concerned about the poly count, how about aiming for 250-500k or under?
That being said, you should take all the advice given to you in this thread besides mine as well. It's really quite good.

OK, these are the statistics. The whole mine mesh is 5,043,690 triangles. The chunk with more geometry in it has 491,389 triangles as shown in the following image:

image.png

Well, the engine doesn't tell the draw calls after all but It shows other interesting info about the scene being drawn.

I'm pretty sure I know someone who was able to get 1 million polygons running on a HD 4400 without a lot of passes.

I assume Intel HD 4400. I think that's good news, as long as my scenes stay below that, that GPU and others of the family will handle the game correctly.

Everyone seem to agree that the polygon count of the map/level is not something to worry about, maybe that's the reason I can't find any information about that. Nobody is giving numbers about the poly count of their maps while finding info about the poly count of main characters and enemies is easy.

Well, that is a rather high triangle count for the short viewdistance you have there. From guessing there are about 20 or so of your panels visible, as well as the ground. I GUESS the engine is only frustum culling (culling everything that is not in the camera frustum), and not culling the invisible geometry behind the walls.

If you could get the engine to cull the invisible geometry, your setup might work just fine for an indoor level. What JMonkey engine calls this IDK, that would be occlusion culling in Unity. Have a look for it, I sadly couldn't (cannot get the jmonkey website to work for me... weird).

Now, 2000 polys for a single wall panel IS rather heavy (don't forget to double it to get the triangle count, unless you already worked with triangles... the GPU can only work with triangles, so quads get converted).

You really sure you cannot lower that slightly? You could still displace your polygons, maybe you would get a little more jaggies, but depending on how much you offset, not that much (your rock there is looking weird at places because of the large offset anyway).

Then, while it is true that culling MIGHT not work if you do combine all the panels in the level into one object (depends on the culling, if its culling of objects or triangles... IDK what jMonkey engine does. For Unity, at least occlusion culling only works for objects.), you should still be careful.

Without batching, you are putting yourself into danger of choking the CPU with draw calls. Find out what JMonkey eninge does for batching of static objects. If you can make the engine treat all these panels as a single batch when sent to the GPU, your drawcall count should improve significantly. At that point, you basically get the low draw call count of a single object, while still allowing the occlusion culling mechanism (should there even be one available) to do its work should it work on objects as in Unity.

My recommendations in short form:

1) Find out if there is an occlusion culling mechanism in JMonkey engine and use it.

2) Find out if there is a static batching mechanism and make sure it is active for all your panels.

3) See if you could reduce the polycount of thos panels... with proper ompimization, the visible poly count should be okay, but I would rather use the polys for objects that make better use of it than just a displaced rock wall.


Frames per second: 184

You're probably good.

That is about 5.4 millisecond per frame.

A better measure in is a rolling statistic, perhaps once per second, with the minimum, average, and maximum times between display, in milliseconds. Perhaps you may see 3.24/5.43/5.98, which tells you all the frames are going along at a nice pace, or you might see 0.45 / 5.43 / 206.34 which means you've got a lot of very fast frames and occasional frames that are terribly slow.

As long as you typically remain under about 10 ms/frame, you're frame rate will be rock solid to the player. You've currently got about 4ms per frame, or about half a graphics frame, to play with.

This topic is closed to new replies.

Advertisement