I’ve been working on a lightweight font library for use with OpenGL 3. The idea is, the library fills out vertex positions and texture coordinates, and you can add any other attributes such as color/jitter with your own vbos (you use your own shaders and vao.)
Feedback is much appreciated.
Thanks for the feedback.
I (hopefully) improved the readme and took out that rebind.
To be honest, I really don’t like how the attributes are bound. As it is now, a new VBO is created for each Text object, which leaves many small VBOs being created. The problem is that users need to be able to use their own VBO(s) to supply their own additional attributes, so I just had them create the VAO and give two attribute indexes to the draw function, but obviously there must be some cleaner way. Any suggestions here are welcome.
I would suggest allowing the user to give you a buffer object and a byte range for you to fill in. Or even better, instead of filling in a buffer, you provide a callback that gets called once per glyph with rectangles for the texture coordinates and location of that glyph.
These should be advanced interfaces of course. There’s something to be said for the simplicity of a quick and dirty “DrawString” function.
I see that your API allows the user to specify a texture. This is good, but it would also be good if your API allowed the user to specify a texture format instead of the texture itself. That way, your internal code can manage the texture storage, but the user can customize the format as they see fit. You wouldn’t need to support everything. Just the ability to pick luminance vs. intensity (failing if those are not supported by the implementation. IE: if it’s a core context) vs RED8 vs RED16 vs. RGB8 vs. RGB16.
Also, you should allow array textures. Just in case an 8192x8192 texture size isn’t big enough for all of the glyphs. Again, this would be at the behest of the user, since they have to treat array textures differently.
A callback sounds great. That way they can interleave the data or do whatever they want with it, and I could then get rid of the attribute setup each draw since they handle all of this.
I removed internal texture handling because users need to be able to modify the texture/parameters in any way and they can make the texture sized according to the number of glyphs they expect to load, since the texture can’t change size.
How would just switching completely to an internal array texture be. I was also thinking of not making a texture per face, but instead make a single texture (would be in the Library class, and using callbacks they could manipulate the font as it’s created) that would store all sized glyphs from all fonts, so that a string containing different fonts could be created and rendered in one pass. Obviously this array texture would have to expand, but it would need to copy all parameters set by the user each time it expands. I want to avoid making custom parameter functions and just let them use the OpenGL ones on the texture, but exposing this internal texture isn’t the cleanest either.
Also with using one texture for all fonts, users could specify the font size when creating the string (and change the size during callbacks) and the Font object could be ditched.
It seems like what you really want is to separate glyph management (ie: how the glyphs are stored in textures) from the typefaces themselves (ie: the things that generate glyphs). Essentially, your typeface class should be given a glyph manager, and it will allocate glyphs from that object. Other typefaces can share the same glyph manager, and thus store their glyphs in the same place.
This way, the user decides if they want to store the glyphs in a global texture, or have different textures for different typefaces.
I refactored Shikoba and made it more low level. It no longer handles strings, only glyphs. Hopefully projects using it will have less static text this way, and can do more interesting layouts.
Shikoba doesn’t mange VBOs anymore, but it now does manage it’s texture. All it does is gives you tex coords and vertex positions for any requested glyph, which you can do whatever with.
Also, everything is done from the Library now. The Text and Font classes I removed in favor of library.setFont() and library.setSize() which allows for changing them easily mid-string.
It seems much better this way, but tell me your thoughts.