Performance of >500 TextNodes

Greetings. I’m working on a text-heavy scene graph and having performance problems. Here are the bullets:

  • Windows Vista, 4GB, DX11 (though Panda3D is using 9, of course), Celeron @ 2.2 GHz
  • I don’t know what graphics chipset my machine has–probably not great: it’s a four-year-old laptop.
  • Display: 1600 x 900
  • ~500 TextNodes
  • ~12 characters per TextNode
  • ~ 50 of the TextNodes have cards
  • I’m rendering both sides
  • Font = Arial Black
  • load-display = pandadx9
  • font.pixelsPerUnit = default (which is 30; I’ve tried it as low as 10)
  • myTextNode.setFlattenFlags(TextNode.FFDynamicMerge | TextNode.FFStrong) on every TextNode.
  • textNodePath = symbolRoot.attachNewNode(myTextNode.generate()) for every TextNode.
  • TextNodes will change during runtime; I can’t just flatten my entire scene graph.
  • Here’s the dump from node.analyze(), which I confess I don’t fully understand:

907 total nodes (including 0 instances); 0 LODNodes.
1 transforms; 7% of nodes have some render attribute.
475 Geoms, with 475 GeomVertexDatas and 2 GeomVertexFormats, appear on 475 GeomNodes.
21908 vertices, 0 normals, 21680 colors, 21908 texture coordinates.
GeomVertexData arrays occupy 513K memory.
GeomPrimitive arrays occupy 64K memory.
388 GeomVertexArrayDatas are redundant, wasting 79K.
412 GeomPrimitive arrays are redundant, wasting 63K.
10954 triangles:
114 of these are on 57 tristrips (2 average tris per strip).
10840 of these are independent triangles.
1 textures, estimated minimum 64K texture memory required.

I’m getting between five and ten fps on a full-screen window as the camera rotates around the scene graph, which strikes me as low.

Is there anything more I can do to improve performance?

Many thanks.

try disabling dynamicMerge and textFlatten. maybe you cpu is not fast enough to merge the texts.
i used to have (maybe) a similar problem, drwr told me the above and my problem was solved.

or 500 text node is really too much for a pc.

MichaelPanda,

Thank you for the suggestion. I tried it but there’s no perceptible difference. Perhaps you’re right: perhaps a PC simply can’t handle this many TextNodes. I wonder whether there’s some way I could do this with textures…or would I just run into the same problems?

There may be a way to get ~500 TextNodes to work well, but I leave that for those better versed in the appropriate matters.

If it isn’t feasible, however, and you only update a small number of TextNodes per small interval of time, perhaps you could get away with something like this:

Apply a single large quad to your entire screen, and keep a small number of TextNodes. When you want to change a piece of text, move a TextNode to that region and apply the text. That done, draw the result into the large quad and hide the TextNode, creating the impression of a large number of active text objects without actually maintaining that many. You might want some internal representation of the nodes – a dictionary mapping TextNode “names” to positions and sizes, for example.

Thaumaturge,

Good thinking. I’ve actually now gone so far as to flatten the whole scene graph–I think I can live with static text for the time being–so I’ve bypassed the need for your idea for now; I may yet have reason to return to it. All that’s happening currently is that a camera is flying around a frozen text structure. Even so, the frame rate is very poor (10-15 fps), and I’m now on a “real” machine with real graphics hardware. I looked at pstats and it tells me that I spend most of my time in the red (drawing) and almost no time at all in Python. How is it possible that the whole unchanging scene graph isn’t effectively cached on the graphics card (I imagine it doesn’t exactly work this way) and rendered at a blazing 60 fps?

This is becoming disheartening. Any additional help would be greatly appreciated.

UnbreakableToy

Try a single call to “render.ls()” at some point after you’ve finished setting up and flattening your scene, and please post here the results.

(Note: don’t let this method be called in a loop – it outputs to the console, so you’ll likely end up with a long stream of repeating text to pick apart, I believe!)

What may be happening is that the “flatten” method may not be properly flattening your scene: if I recall correctly there are circumstances in which it won’t combine the geoms in question, potentially leaving you with little gain, if any.

Another thought comes to mind; it seems unlikely, but it also seems worth checking just in case: you’re not calling the “flatten” method repeatedly, are you?

Finally, which “flatten” method are you calling?

Thaumaturge,

I did try your ideas/hints, but I couldn’t get any performance boosts. So I gave up and decided to take a theatrical rather than a technical approach. I’ve reworked my scene so that most TextNodes are invisible at any given time–they reveal themselves in response to user actions. It’s not perfect, but 1) what is? and 2) at least it’s 60fps.

Thanks again,

Ed