glBitmapText

It would be really nice to improve text handling inside OpenGL. Today, it is enough to handle UTF8 encoding, programmers are able to transfer to this always, and already most of programs are using this format. Also, several (3-4) PS fonts will do the job for most programmers. Functions could be:
glSelectFont(int font_id, int size); (Time consuming operation which translates vector based PS font to bitmaps).

glBitmapText2i(int x, int y, char* utf8str);

Of course there should be buffer for 8-9 font/size combinations, so glSelectFont() takes long only first time.

[This message has been edited by mirza (edited 02-24-2004).]

Personally, I don’t think Text is GL’s responsibility. There are system-specific calls for generating display lists of characters in a particular font, i.e. wglUseFontBitmaps. Which is adequate for most purposes.

Given that GL is client/server, how would the client communicate the necessary font information to the server? Can’t just be a name, since the NamedFont on the client, might not be the same NamedFont on the server. And standardizing fonts to numbers might be a nightmare.

If UTF-8 and C-style strings were adequate, openGL extensions would have chosen to use them. They didn’t so choose for very good reasons, as explained in their respective extensions.

BEGIN DEVIL’S ADVOCATE

void glGenFonts(GLsizei n, GLuint* fonts)
This function generates n font names(as in glGenTextures texture names).
void glDeleteFonts(GLsizei n, const GLuint* fonts)
This function deletes n font names, ignoring zeroes and invalid names.
GLboolean glIsFont(GLuint font)
Determines if font is a valid font name.

void glBindFont(GLenum target, GLuint font)
This function enables the creation of a named font bound to the font target.
target:GL_FONT_2D, GL_FONT_3D

void glFontImprint(GLenum target, GLint internalformat, GLdouble width, GLdouble height, GLenum format, const GLvoid* chars)
target:GL_FONT_2D, GL_FONT_3D
internalformat: GL_RASTER, GL_GEOMETRY, GL_POSTSCRIPT, GL_TRUETYPE
height and width are bounding boxes for the individual characters.
format: GL_RASTER, GL_GEOMETRY, GL_POSTSCRIPT, GL_TRUETYPE
chars is a pointer to the full font’s description of every character. Data is determined by the format.

glText(GLsizei count, const GLubyte* string)
render the string at the current raster pos. If font internalformat is GL_RASTER, then behave like glDrawPixels for every step; is GL_GEOMETRY, then at the current raster position apply the character as glVertex functions; is the others, then behave appropriately for that type.

END DEVIL’S ADVOCATE

Again, there are still problems even with the above. How are unicode characters rendered(if at all)? Does glFontImprint need a length for chars? (Where’s glFontSubImprint?) Is this too slow(probably)? Why are PS and TT font formats and not __ and __ font formats included? How do I get (and communicate to the GLserver) my system fonts?

Originally posted by chemdog:
If UTF-8 and C-style strings were adequate, openGL extensions would have chosen to use them. They didn’t so choose for very good reasons, as explained in their respective extensions.

Which extensions you mean? UTF-8 is perfectly adequate for the job.

As you might notice in my posting, I didn’t mean to use >all< system fonts inside OpenGL. I think that most applications (CAD, Scientific, Mapping etc.) will benefit if there is small set of fonts (like in GLUT) binded to IDs, that can be converted from vector to bitmap format for performance reasons in runtime. These 3-4 fonts can be built-in inside opengl library. Of course, these fonts should cover as many unicode chars as possible. Even if only ONE (1) font exist, for a start, many applications would have problem solved.

The other extensions that use text strings, i.e. the vertex/fragment program/shaders.
From several of the extensions there are issues that match this one (from vertex programs).

(45) Should programs be C-style null-terminated strings?

RESOLVED: No. Programs should be specified as an array of GLubyte with an explicit length parameter. OpenGL has no precedent for passing null-terminated strings into the API (though GetString returns null-terminated strings). Null-terminated strings may be problematic for some programming languages.

(31) Should this extension provide support for character sets other than 7-bit ASCII?

RESOLVED: Provide a <format> argument to ProgramStringARB to allow for future extensions. Only ASCII will be supported by this extension; additional character sets or encodings could be supported using separate extensions.

Since GL is language(written language) independent, it would only be fair that every language (all 300+ of them) should have their respective vharacters included.
So American English gives (26 chars), European (30 more), Asiatic (about 75,000). And to be fair, more people speak Chinese than any other language.

If included in the main GL, NVIDIA, ATI, MATROX, and other companies must include glyphs for up to 4 billion characters. (Unicode has 1 million characters reserved now, about 200K in use.).

There is a project called FreeType, and NeHe has a tutorial using it. It allows one to use (TrueType)-like antialiased fonts with GL.

These are only artificial internal standards, like: let’s not support null terminated strings. There are lot of other graphic libraries (GDI and Qt being most famous) that has no problems drawing unicode text alongside other graphic primitives.

OpenGL already provides enough functionality to render text. There is absolutely no need for extended core functionality because you already can layer text rendering on top of OpenGL. Freetype be my witness.
Why should every OpenGL implementor reinvent this particular wheel?

How is a glyph conceptually different from any other bitmap or texture? It isn’t. So adding it to the core would be completely redundant. Even so, without resorting to layered libraries, there’s already some partial support for that in unextended GL. wgl lets you convert system fonts to bitmaps. glListBase and glCallLists were designed almost exclusively with text rendering in mind.

What more do you really need? The tools are there, all you have to do is stitch them together. Programming is all about solving problems with what little tools you have. If you can’t do that … well.

As for zero terminated ASCII strings, that’s C. Eg Pascal (aka Delphi) does things differently.

Yes, I am able to collect all sorts of libs and put it togather to paint text “on top” of opengl image, but the point is that on every platform I will have to use different code to achieve it, while OpenGL should provide a way to draw graphics in platform independent way. Like it or not text IS graphic primitive, like triangle or line, and should be treated accordingly. Maybe glu would be better place for this then gl library, but library should take care also of Scientific/Mapping/CAD/2D users, not only Gaming industry.

Like it or not text IS graphic primitive

Unlike (say) triangles, text isn’t a very well defined primitive though. Should it be made of lines? or how about polygons? How good is the tessalation? How does one specify fonts or sizes? How to make it consistent accross systems? Or maybe it should be texture mapped? What about filtering then? What if you wanted to apply font effects like italics? ASCII vs Unicode, etc.

Things get really complicated really fast.

Instead, GL opted for the simpler route: leave this to the user apps.

Yes, I am able to collect all sorts of libs and put it togather to paint text “on top” of opengl image, but the point is that on every platform I will have to use different code to achieve it

In what way is this code platform specific? The rendering of text is quite platform neutral, once you have the font in some form of OpenGL data. Getting the font there may be platform specific, but OpenGL should never be required to provide such functionality. You may as well start asking for file formats/loading and so forth.

Even if only ONE (1) font…

To hyperbolize my point, I nominate wing-dings as the standard GL font.

Like it or not text IS graphic primitive

Text is not a graphic primitive. Text consists of symbols(characters), each of which is ideographic or pictographic. Every character in every languages is composed of dots and lines(not necessarily straight). Text is a composite of different primitives.

It was a big deal when QUADs were added to the set of basic GL primitives. Even now, many implementations break a QUAD into 2 triangles. It was a big deal adding a primitive that was composed of 2 other primitives. Imagine how big a deal it is to add 250K new primitives, each of which consists of several base primitives.

…other graphic libraries (GDI and Qt…

Qt is a windowing toolkit, and GDI is part of a windowing toolkit(Windows). Windowing toolkits are to communicate with the user so naturally they would include text. (Their choices for effective communication being, text(visual) or speech(aureal)). Using Qt or GDI is no different than using wgl, and Qt is as platform independent as FreeType.

GLUT is a windowing toolkit. The proper place for text support is GLUT. Now, go convince Mark Kilgard, and whomever else is necessary, to incoporate text in GLUT 4.

Good to see people discussing improving text support in OpenGL, bad to see no one seems supportive of the idea.

Text is my biggest headache with OpenGL. There are certain things you simply can’t do at the moment, such as centering or right-justifying text (please let me know if I’m wrong!). Most people don’t care because most 3D scenes don’t contain text, or if they do, it’s 3D text. I’m interested in text that stays the same size and orientation, but can still be positioned in 3D.

Text can be drawn with wglUseFontBitmaps(), glRasterPos3fv() and glCallLists(), but the options are very limited. The main thing I wanted to do for example, and have now given up on, is centering text. I think the app would have to get the viewing & projection matrices, transform the 3D text position to find where it goes on the screen, offset this position by half the text width, invert those matrices, and transform the new position back into 3D coords. I need to use the 3D coords so that the text can be put into the Z buffer correctly. That’s a lot of overhead just to draw some centred text.

This must be a common problem in visualization software, where text is used to label various items. I imagine most (all?) programmers have to settle for left-justified text.

I might be mistaken, but I have a feeling it’s equally hard to centre a bitmap.

Rob.

If you want to depth-buffer Raster(Bitmap) Text, that’s a difficult problem discussed in the appendix of the RedBook(As Depth-Buffer Images). Centering is trivial(no really), adjust the Raster Position, by half the string length multiplied by the width of a character(probably 8 pixels). The only catch is you might render off the screen if you push too far left in centering. Or with long strings render off both sides of the screen. Assuming, of course the driver doesn’t kill the system for moving the Raster Position into a “weird” place.

Geometry Fonts Or Text Billboards can also be centered, and are trivially depth-bufferable.
Direction Vector needs to be in the same direction as you want to adjust the text. Assuming the model-view matrix is adjusted to the where the center of the text should be.

glTranslate(UnitDirectionVector * half the width);
DrawString;
glTranslate(UnitDirectionVector * - half the width);
UnitDirectionVector is probably (-1,0,0), to move left. Other transformations can adjust the necessary value for this vector.

OpenGL is not a text layout engine. Text layout is complex and has no business being rolled into GL.

Text alignment is one of many non-trivial elements of a proper layout engine which have to be considered. Take a look:
http://developer.apple.com/documentation…_section_8.html

Another (perhaps better) example of text layout would be to read the collected works of Donald Knuth, particularly Computers & Typesetting. Additionally, the supplements to TeX that add unicode and internationalization support for non-english languages.

I think a big distinction should be made between DOCUMENT, TEXT, and CHARACTER support.(And I will shout their names because I am going to make a big distinction between them.) CHARACTER’s are dumb: they don’t know about their context, and they are nothing more than a graphical description of a symbol. TEXT’s are intelligent: they compose characters into ligatures, they are knowledgable about arrangements like italic correction, they are translatable in a meaningful way, and contain logical markup. DOCUMENT’s are intelligent: they understand directionality and flow of text, they compose texts into higher order structures, and they are responsible for the physical markup.

For a rough analogy, when people communicate: they communicate ideas using TEXT’s; the language they communicate in is of CHARACTER’s; and conversations are representable by DOCUMENT’s.

Whenever there is a separate library suggested, OpenGL could possibly “honor” a specific one, which would be the unofficial official library. OR perhaps a new GL* library could be created.

CHARACTER support should either be included in GLU(perhaps as an extension), or in a separate library. People will find this the simplest way to do their desired programming. This is toy programming(no offense intended).

TEXT support should be included in GLUT(all windowing toolkits really), or a separate library. The largest difficulty here is internationalization. A sentence on my machine, should mean the same, as it does on yours. Programmers will find this the appropriate way to do their programming. This is application programming.

DOCUMENT support is too complicated to be included in anything but an OS, or GECKO, or TeX.(whatever you personally feel belongs or doesn’t belong here, as this isn’t worth even one flame). This is library programming, the hardest form of programming to do correctly(as everyone else is out to destroy your code, even accidently, and if anyone does or even could possibly do you have failed).

[ul][] Summary Of Suggested Locations[] CHARACTER - GLU, FreeType, other font managers[] TEXT - GLUT, other internalization libararies[] DOCUMENT - External Library[/ul]

chemdog wrote:

> If you want to depth-buffer Raster(Bitmap) Text, that’s a difficult
> problem… Centering is trivial(no really), adjust the Raster
> Position, by half the string length multiplied by the width of a
> character(probably 8 pixels).

Seems to me the opposite is true. Depth-buffering raster text is easy, but
centering it is difficult. I use glRasterPos3dv() to position the text. It
happily gets clipped by other objects. But since the position is given as a 3D
coordinate, I can’t easily offset it in screen-space.

I would have to get the projection/modeling transforms and use them to find the
true 2D screen position of the text, then offset it by half the text size, then
invert the transforms and apply them again to get the appropriate 3D position.

Is there some way to offset the final screen raster position that I don’t know
about? Using glRasterPos3dv() means that the raster position is 3D. OpenGL’s
pipeline must end up figuring out where to draw the text in screen coordinates,
but there’s no way to access that information back in my app. Would be great
if I could pass a screen offset to glCallLists() or something like that!

I have two apps where centred text would be useful. One is a creator/viewer
for polyhedra. You can see some screenshots here:
http://www.software3d.com/ScreenShots.html
None of them show text unfortunately, but the app lets you display data about
models on the screen. Eg: dihedral angles can be shown at each edge. Depth
buffer is nice because you can’t see text for edges on the back of the model.
However I can’t easily centre the text.

My other app is a 3D minesweeper thing:
http://www.software3d.com/Mines3D/
You can see text in these screenshots. Originally I only used raster text as a
placeholder and planned to use 3D text or textures, but ended up liking it.
The text is always a readable size (ie the same size) even when you zoom in and
out etc. Again, centering the text would be nice, even when it’s only one
character as it is here. People have even complained about the numbers not
being centred over the tiles!

arekkusu wrote:

> OpenGL is not a text layout engine. Text layout is complex and has
> no business being rolled into GL.

Sure, but OpenGL also shouldn’t be so limited as to make certain things
impossible, or even more computationally expensive than necessary. The only
way for me to offset raster text that I have positioned in 3D is to get the GL
transforms, convert the 3D pos to a 2D screen pos, offset it in 2D, invert the
transforms and convert back to 3D. That’s a very expensive and difficult way
to draw some text.

Somewhere down OpenGL’s pipeline it knows where on the screen to put that text
(my app only knows the 3D position). So it would be great if OpenGL gave you
some additional control over the final 2D screen position. All that would be
needed is a pixel offset to the final 2D position.

I understand that it is also a bad idea to mix rendering methods in an OpenGL
window. For example, don’t use Win32 commands. If that’s true then there’s no
option other than using OpenGL for text. I mean, wglUseFontBitmaps() does most
of the work, but OpenGL must still be used to position and draw the final text.
A bit more control over it’s final screen position would be very helpful, for
other bitmaps too I imagine.

Rob.

I agree that gluProject is not the most efficient way to do screenspace transforms. Perhaps you could look at tweaking your projection matrix temporarily around text drawing to do the translates in screen space.

However, this is not the only way to render aligned text. How about:

Make an OS textview.
Draw text into it, with all the fancy unicode fonts and alignment etc you want.
Make a texture from the view.
Draw the texture in a quad.

This is much easier than implementing an entire text layout engine. Of course it depends on the OS text engine.

This code works for geometry based fonts. Such as Billboards or nurb-Text.

glpushMatrix();
glLoadIdentity();
//Do Text Movement To Text Location Center
glTranslate(text_x, text_y, text_z);
//Center by moving left
glTranslate(-(text_length/2, 0, 0);
//Draw Text
DrawSting(“Hello World”);
glPopMatrix();

Of course, you would need to know where you wanted the text in world coordinates. Probably not a problem for the geometry-app.
And all text calls can be batched at the end reducing matrix ops.

For fonts that text is drawn with xxxPixels, you need to use the glu function or equivalent.

For minesweeper3D if you could keep a transformed normal with each face, then you could find left with a few vector ops. Essentially you’d be precomputing the glu functions.

I love it when arekkusu points out a solution that’s 3 lines in OSX, and hundreds in Windows. It really makes my day. Thank you. (though I am starting to miss Cocoa).