tonihele / OpenKeeper

Dungeon Keeper II remake
GNU General Public License v3.0
437 stars 41 forks source link

Reduce the complexity of the scene graph #93

Open tonihele opened 8 years ago

tonihele commented 8 years ago

Reduce the complexity of the scene graph. It causes major FPS loss on big levels. JME 3.0 "recurses into the scene graph 3 times every frame". So even when nothing happens and looking in the darkness. I only get like 40 FPS on "level15a". This is fixed/changed in JME 3.1, and it just might do the trick. But also it is quite complex and by simplifying it we might save a bit. See: http://jmonkeyengine.org/301772/jmonkeyengine-3-1-alpha-1-released/

KmfLoader wraps everything in "Root" node, it has one or more nodes beneath it. Usually unneeded.

I tested this a bit: By removing the root node (return (root.getQuantity() == 1 ? root.getChild(0) : root);) I got 54 FPS on the level

By removing all unnecessary nodes with

    /**
     * Helps reduce the hierarchy complexity by stripping extra nodes away
     *
     * @param spatial starting node
     * @return the simplest possible hierarchy
     */
    private Spatial stripExtraNodes(Spatial spatial) {
        if (spatial instanceof Node && ((Node) spatial).getQuantity() == 1) {
            Spatial child = ((Node) spatial).getChild(0);
            child.setLocalTranslation(spatial.getLocalTranslation()); // Carry down the translation
            spatial = stripExtraNodes(child);
        }
        return spatial;
    }

I finally hit the limiter.

This might also be logical, or not. But after these alterations, the whole terrain/building construction is messed up and needs to be adapted to this.

ArchDemons commented 8 years ago

Frustum Culling + Quadtree help us.

tonihele commented 8 years ago

Interesting reading. I guess we kinda have them already. We now have 8x8 "buckets", with floor, walls & ceilings as a separate batch node. All index referenced (fast). So culling will occur automatically by JME by those 8x8 buckets. Something along those lines.

But by introducing additional nodes, I created a new problem. I would say this is because of how JME 3.0 works. It traverses the nodes unnecessarily. So the problem is not the GPU anymore, it is now more CPU. 3.1 JME should resolve this on its own. But good to have an issue about it at least.

tonihele commented 8 years ago

It is quite fast now, even with that monstrous culling limit. So unless there is nothing else to do, perhaps it is not wise to invest in this. Probably all is going to be rewritten with the #108. At least the lights & shadows will have an impact on the performance on all implementations, so it is best to wait at least for those.

Trass3r commented 2 months ago

Also see https://discord.com/channels/318359390916837378/318359390916837378/1095792040643661894

tonihele commented 2 months ago
  • instancing should be used where appropriate

Note that instancing doesn't reduce the amount of draw calls. It helps with complex meshes. In our case I would say that batching/combining meshes, like gold piles and chests, would be better.

Trass3r commented 2 months ago

Not sure how you mean that, the whole point of instancing is reducing draw calls. https://learnopengl.com/Advanced-OpenGL/Instancing

tonihele commented 2 months ago

Not sure how you mean that, the whole point of instancing is reducing draw calls. https://learnopengl.com/Advanced-OpenGL/Instancing

Hmm, yeah, now I maybe mixed it with object count. Object count is a concept in jME engine itself. While not a huge problem anymore with these modern jME versions, we should still remember this as well. Instancing doesn't affect object count but batching does (positively).

Trass3r commented 2 months ago

Object count is a concept in jME

I guess ~ number of nodes in the scene graph (after culling?).

tonihele commented 2 months ago

I guess ~ number of nodes in the scene graph (after culling?).

Precisely. Using jME Java class names, spatials in the scene graph rendered (after culling). With instancing (using instanced node), all the spatials are still in the scene graph and add to the object count. Batching combines similar spatials to a single mesh and it is only then a single spatial in the scene graph.

Instancing should be fairly easy to achieve. I'm not sure what it means when culling (i.e. should we try to be smart about their location and group them accordingly?). All the objects can be just dropped to a instanced node. That is my assumption.