Brief Description
The way of DarkPlaces to render text is unfriendly to CJK text.
There is too much overhead on "caching", causing bad game performance.
Good fixing should be possible, by reworking on that part.
Below is detailed analysis. Idea to solution is at bottom.
Symptom
The game will "lag" for few frames when showing individual CJK string for the first time.
It's simply annoying, period.
The impact of the game Xonotic is described here in Xonotic Forums. In which reply #11 also have explanation, but you may want to read this issue instead.
Basic Concepts
-
CJK: Shorthand for Chinese/Japanese/Korean.
CJK characters are so many, occupying large amount of Unicode code space of Plane 1. Just common "CJK Unified Ideographs" range from U+4E00 to U+9FFF, that's 20992 ones.
-
The way of DarkPlaces to render text:
- DP will render (from ttf/otf) & cache the font texture as maps, on demand if required, as seen around here. Rendering is resource-costing, but only once.
- By default a map is 16x16 chars in size, as in these constants; that means 256 chars will be rendered, whenever a single character among them is on the way, as in this
for
loop
- At very start DP will cache the very first ASCII chars, that means languages like English will only need one or two additional maps -- DP just use the cached ones all the way
- It's applicable to most of Western languages, and is indeed working well
But, matter is going different on CJK text.
- A typical Chinese sentence have several characters
- But, unlike Western languages, the chars will spread across several "maps"
- The worst case is that every character will cause a fresh "map" to be rendered & cached, and that's the usual case
- That further tells, about 255x of the effort is overhead. More than that, most of cached chars are uncommon and won't ever be used in the game, so isn't optimal at all
So, when players use CJK language:
- Earlier in the game, players will experience graphical lag very often. It's very unpleasant in a fast-paced game like Xonotic
- Though, it's lesser after caching many of the maps. But of course higher the memory cost.
- Well, not the end yet: the texture cache slots have limit (I see Xonotic have 1024), they will run out, sooner or later, after that following in-game textures will appear to be gibberish (indeed becoming texture of the first font map), only restarting the game can save
- Experience the fear again from the begining!
What can help?
I had some trials to reduce the matter, but they are ineffective to the real problem.
Click to expand anyway
To decrease chars-per-map:
- Yes, by halving the count, the game become far less laggy. But the overhead is still there, useless chars are still rendered, and cache slots run out even more quickly.
To increase chars-per-map:
- Only see segmentation faults, by out-of-memory. It isn't realistic to put all of the chars in few maps either.
To increase cache slots:
- Not so good. As said, it runs out sooner or later.
The only future-keeping approach in my mind is to rewrite the corresponding procedure, to:
When encountered those CJK chars, instead of regular mapping, reserve some kind of special texture map, to cache the only used chars, incrementally, one by one. And also keep an array map, query existing chars with that.
And that's all other games around (free or proprietary) are doing: only used chars are in the assets.
Thanks for the Great engine, flexible like that! Best wishes :)