haymo's picture

Multiple Font objects

I experience strange behavior with TextureFont and TextRenderer: TextureFont seems to shuffle the glyph <-> char mapping _sometimes_ :(
Steps to reproduce the behavior:

Call the following snippet more than 15 times - once per rendering frame. Every time 'text' should be only one char. Each char should be different.

 //... other rendering stuff
TextHandle handle; 
m_textPrinter.Prepare(text,m_font,out handle);
m_textPrinter.Begin();
using (handle) 
    m_textPrinter.Draw(handle); 
m_textPrinter.End();
//...finish other rendering stuff + swapbuffers

Once 15 chars are loaded into the font, the output gets scrambled, ie. where "a" should be - is now "5" or something completely different, even blank space. It is not deterministic, what is drawn instead. But it is deterministic, that a false texture is drawn.

Also, the bahavior does not happen, when loading more than 15 chars at once, but only by incrementally loading the chars in the way shown above.

Dont know if '15' is specific to my machine either.


Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
the Fiddler's picture

Can you please upload a complete test case?

haymo's picture

Hm, was afraid, you could request this :| - ok. the testprogram attached reproduces the situation on my machine. Unfortunately It does not on another machine. (But I think, I have seen it there also - not sure about this).

the package attached contains the code, an VS2005 compiled exe and an altered version of OpenTK. (To reproduce the modifications, you would have to change the GLControl related 'internal' classes to 'public' in OpenTK - thats it.) Also, there are 3 images contained, showing the visual effect on my machine.

After starting the app, enter the following string into the textbox:

abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789...!

(one by one character, not copy and paste!) On my machine, the effect sometimes shows after the "r" - sometimes later.

To me, it seems, the effect is caused by having too many TextureFonts created. Is there an official limit? And if it is related to my machine - how can I prevent it and/or query the maximum number allowed at runtime ?

[Dont know, how to attach a file here, so I uploaded it to: http://ilnumerics.net/files/WindowsApplication3.zip ]
Thanks so far!

the Fiddler's picture

Thanks. The reason I asked for the test case, is that I have limited time to work on OpenTK, so it's best to minimize overhead when developing/debugging :)

Can you try this? Hold '1' for a little while, then type '2': "111111111111111112". Does the string display ok? Here, all letters turn to '2' - pressing 1 or 2 results in a 2 being displayed.

(Investigating)

haymo's picture

Ah, great enough, you can follow the issue!
On the machine, which always failes (WinXP Tablet PC Ed., Mobile Intel 915GM, 910GML Express Chipset) all 1 turn into 2.
On another machine (Ubuntu 7.10, GeForce FX 5200) it runs smoothly - no change while pressing 2.

the Fiddler's picture

Ok, individual glyphs are currently inserted into a binary tree for packing - it seems that narrow letters, like 'l', 'I' or '1' may cause problems.

Argh, too tired right now, will check this hypothesis tomorrow.

haymo's picture

you are probably right. I also expect the source of the problem somewhere near or inside TexturePacker. Couldn't really get into it yet. But I'm not sure, if this is the only problem associated with this issue. Im only guessing, since I dont even understand in detail, how the TextPrinter works. I assume, all textures for chars are layed out on an area. Drawing a char than means, drawing a rectangle with a texture bind to it, where that texture will point to the subrectangle in the source area, corresponding to the char. Is this correct understanding?
Now, in the failing situation, after adding a new Glyph to the Font, this offset into the texture-char-area seems somehow to be incorrect. While your '1111112' example demonstrated, that the mapping of Glyphs to chars is malfunctioning, here I most the time see the offset to point somewhere outside the texture area. This causes the corrupted 'chars' to look like beeing composed out of random lines or even random noise?
Maybe some Size measurement problem? Strange, that it works fine on another machine... Hm.

the Fiddler's picture

I find it interesting that it breaks on individual characters, but not on larger strings. It is also strange that it works in some computers, but not on others.

The current implementation works like this: individual glyphs are rasterized on demand, and "packed" into an OpenGL texture using the TexturePacker. TextPrinter composes strings into VBOs of quads, with each quad displaying a single character.

This looks like an error in TexturePacker, which either packs some glyphs incorrectly (overwriting existing entries), or returns wrong positions for packed glyphs. Try modifying your test case to render a single textured quad inside the TextPrinter.Begin/End block (texcoords from 0.0 to 1.0) - this will display glyphs as they are packed into the texture.

I've just found the root of some crashes on Linux, will focus on this issue once these are fixed.

the Fiddler's picture

I find it interesting that it breaks on individual characters, but not on larger strings. It is also strange that it works in some computers, but not on others.

The current implementation works like this: individual glyphs are rasterized on demand, and "packed" into an OpenGL texture using the TexturePacker. TextPrinter composes strings into VBOs of quads, with each quad displaying a single character.

This looks like an error in TexturePacker, which either packs some glyphs incorrectly (overwriting existing entries), or returns wrong positions for packed glyphs. Try modifying your test case to render a single textured quad inside the TextPrinter.Begin/End block (texcoords from 0.0 to 1.0) - this will display glyphs as they are packed into the texture.

I've just found the root of some crashes on Linux, will focus on this issue once these are fixed.

haymo's picture

The problem comes from the TexturePacker beeing static for all TextureFont objects. Once a Font is disposed, it sets the TexturePacker object to null, which causes it to loose all previously creates glyphs.
I (hopefully) solved the issue provisional by making texture packer and texture an instance member. This seems to work - but do you see any drawbacks for it?

For the future, I could imagine, improving some of the TexturePrinter design. Maybe I'll try to clean up the class hirarchy a little (less interfaces, more abstract classes, but its only my taste). Would you be interested in contributions regarding to that?

the Fiddler's picture

Thanks, I see the problem now. The TexturePacker is shared between TextureFonts to improve performance (minimize texture switches) and reduce wasted video memory.

That said, the text engine is still in a primitive state - improvements are welcome. :)

What changes do you have in mind?