Changing text colour half-way through?

Hi,

I use glCallLists() to render text strings in OpenGL (to show annotations attached to vertices in 3D).

I can call glRasterPos3fv() once, then call glCallLists() several times. The first time starts at the raster position I set, the subsequent calls continue the text from where the previous text left off. This is great.

But I want to change the colour between calls to glCallLists(). However simply using glColor3fv() doesn’t work. It works if I call it before glRasterPos3fv(), but otherwise it doesn’t do anything between calls to glCallLists().

Is there some way around this? (I’m using Windows2000)

OpenGL makes simple raster text exceedingly difficult. I know it’s not OpenGL’s job to handle text, but there are so many common situations that are more or less impossible using any combination of OpenGL and the native OS font functions.

Other examples are centering text, or multi-line text, at a 3D point. If anyone has solutions to those I’d like to hear them too!

Thanks,
Rob.

glBitmap has no means to pick up a color other then from the current raster color and this is set at glRasterPos time. Means you need to change the color of a glBitmap with
glColor;
glRastePos;
glBitmap;
This doesn’t work with the usual glCallLists string printing, because there are no glRasterPos calls inside the display lists.
glBitmap has an offset which automatically advances the RasterPos.

There are some OpenGL text utilities using font textures. E.g. luminance textures can pick up the current color, but positioning works differently with these anyway.

With other (2D) text functions you need to split the different colored text, too.

When specifying the font you can query all sizes of each individual letter (GLYPHMETRICS is mentioned in the wglUseFontBitmaps manual) and position the start RasterPosition correctly justified.
Check GL_IBM_rasterpos_clip for an extension which allows to start printing starting outside the viewport without invalidating the raster position.

Originally posted by RobertWebb:
[b]
OpenGL makes simple raster text exceedingly difficult. I know it’s not OpenGL’s job to handle text, but there are so many common situations that are more or less impossible using any combination of OpenGL and the native OS font functions.

Other examples are centering text, or multi-line text, at a 3D point. If anyone has solutions to those I’d like to hear them too!
[/b]
Well, as you say, OpenGL is not meant for text rednering, and therefore the system font functions are not all that useful. So don’t use them. :wink:

I generally tend towards Freetype and FTGL for text. It’s easy to use, reasonably efficient, and has many different ways to render stuff. And best of all, it’s Open Source, so if you need something it doesn’t do, you can add it.

Originally posted by RobertWebb:
Other examples are centering text, or multi-line text, at a 3D point. If anyone has solutions to those I’d like to hear them too!
Use your brain, perhaps?
And certainly, go to the beginners forum in future, that’s what it’s there for.

Originally posted by Relic:
glBitmap has no means to pick up a color other then from the current raster color and this is set at glRasterPos time. Means you need to change the color of a glBitmap with
glColor;
glRastePos;
glBitmap;
This doesn’t work with the usual glCallLists string printing, because there are no glRasterPos calls inside the display lists.
glBitmap has an offset which automatically advances the RasterPos.

Hmm, sounds like the answer is as I thought then: it can’t be done (in any easy/efficient way).

Originally posted by dirk:
I generally tend towards Freetype and FTGL for text. It’s easy to use, reasonably efficient, and has many different ways to render stuff.
Thanks. FTGL seems like overkill to me for (what should be) simple bitmap text, but I’ll have a look at it.

Originally posted by knackered:
[quote]Originally posted by RobertWebb:
Other examples are centering text, or multi-line text, at a 3D point. If anyone has solutions to those I’d like to hear them too!
Use your brain, perhaps?
And certainly, go to the beginners forum in future, that’s what it’s there for.
[/QUOTE]Well this isn’t very helpful. I’ve been programming full-time (and in my spare time) with OpenGL for more than 13 years now. Although what I’m trying to do should be simple, I ask on the advanced list because I have never been able to find a way to do it, and I have looked all over for answers.

Maybe you could give us the answer if it’s so simple? My brain tells me that it can only be done very inefficiently, by getting the transform matrix, using it to convert the 3D point to a 2D screen pixel, offsetting appropriately based on size of text, and converting back through the inverse matrix again to get the 3D point. Obviously (to any advanced OpenGL user) very inefficient, especially when OpenGL stores the 2D raster position internally and should be able to do all this for you very efficiently.

So unless you put your brain where your fingers are and give us a more efficient method, I’ll presume it can’t be done with OpenGL’s limited raster operations.

Thanks,
Rob.

Look pal, if you have so much experience in opengl you would not be using glbitmap/glrasterpos/glcalllist to render text.
Not if you had any concern for performance and compatibility (wise to steer clear of rarely used functions unless absolutely necessary…don’t give ati an excuse).
Hint: draw fonts into bitmap using platform dependent API, bitmap to texture, orthographic projection, vertex array, texcoords, colour-per-vertex…get the picture?
That’s what an experienced gl user would be doing, given the fact that no text functions are in core opengl.
This question really does belong in the beginners section, where I’m sure there are people there more than willing to help you re-assess your approach to drawing text.

Btw, what makes you think your method with the transformations is so inefficient? After all, you are only talking of calculations that must be done once per line of text. Everything that has to be done less than once per frame would be far less efficient when done by OpenGL automatically.

You shouldn’t confuse “much work for the programmer” with “much work for the computer”.

Originally posted by knackered:
Look pal, if you have so much experience in opengl you would not be using glbitmap/glrasterpos/glcalllist to render text.
Not if you had any concern for performance and compatibility (wise to steer clear of rarely used functions unless absolutely necessary…don’t give ati an excuse).
Hint: draw fonts into bitmap using platform dependent API, bitmap to texture, orthographic projection, vertex array, texcoords, colour-per-vertex…get the picture?
That’s what an experienced gl user would be doing, given the fact that no text functions are in core opengl.

I don’t know why you’re so angry, but thanks for at least giving advice this time (other than “use your brain” and “go away”).

I know about using textures for text in OpenGL. I know it is faster on machines with hardware acceleration. I also know it is much slower on machines without hardware acceleration. There are not so many of those around now, but I know I have users who still have them.

Hardware acceleration also doesn’t seem to get used when rendering OpenGL to a bitmap (maybe I should ask on the beginner’s forum about that :-)), although speed doesn’t matter to me so much there (only for exporting and printing images).

So compatibility-wise, I think raster text is safer (do any platforms not support it?). I didn’t know that glBitmap/glRasterPos/glCallLists where rarely used though.

Ideally I suppose raster text should be used when there’s no hardware acceleration, and texture text otherwise.

Originally posted by Overmind:
Btw, what makes you think your method with the transformations is so inefficient? After all, you are only talking of calculations that must be done once per line of text.
As I was writing that I was starting to think that maybe it wouldn’t be so bad anyway. I’ve always read that “Get” operations in OpenGL are slow (require a pipeline flush etc) so getting the current projection/transform matrix seems inefficient, but I can probably keep track of that myself along the way.

Thanks,
Rob.

Have you tried using the glut function glutStrokeCharacter? It’s works ok depending on what you are doing. I’m using it for two demos I made and what I’m using it for in these demos is to display info about the program overlaying the renering.

What I usually do is use the method knackered suggested by having a bitmap of characters and for each character I want to write out, I look up some texture coords that access that char in the bitmap and map that to a small quad.

Anyway, here is a function I made that draws text using glutStrokeCharacter:

void draw_text( const char *text, float x, float y, float size, float r = 1.0, float g = 1.0, float b = 1.0 )
{
	int i = 0;
	char ch = text[i++];

	glMatrixMode( GL_PROJECTION );
	glPushMatrix();
	glLoadIdentity();

		glOrtho( 0, WIDTH, 0, HEIGHT, -1, 1 );

		glMatrixMode( GL_MODELVIEW );
		glPushMatrix();
		glLoadIdentity();

			glTranslatef( x, y, 0 );
			glScalef( size, size, size );
			glDepthFunc( GL_ALWAYS );
			glColor3f( r, g, b );

			while( ch != '\0' )
			{
				glutStrokeCharacter( GLUT_STROKE_ROMAN, ch );
				ch = text[i++];
			}

			glDepthFunc( GL_LESS );
		
		glPopMatrix();

	glMatrixMode( GL_PROJECTION );
	glPopMatrix();
	glMatrixMode( GL_MODELVIEW );	

	glColor3f( 1, 1, 1 );
}

-SirKnight

Sorry RobertWebb, I was having a really, really bad day. I should learn to avoid the internet when things aren’t going well. :slight_smile:

As I was writing that I was starting to think that maybe it wouldn’t be so bad anyway. I’ve always read that “Get” operations in OpenGL are slow (require a pipeline flush etc) so getting the current projection/transform matrix seems inefficient, but I can probably keep track of that myself along the way.
Get operations can be slow, but they don’t imply a pipeline flush.
You can assume the matrices are in system memory, as are other variables.
Still, I think it’s better to keep local copies in your app.

Pipeline flush occurs when you need a result from the GPU, like glReadPixels.

Hi Robert,

In reply to your original question, here’s a way to change the current raster position color between glCallList() calls:

GLfloat pos[4]; // used below

// set initial color and position
glColor3fv(initialColor);
glWindowPos2i(x0, y0);
// draw a few bitmaps
glCallList(c0);
glCallList(c1);

// change raster color
glGetFloatv(GL_CURRENT_RASTER_POSITION(pos);
glColor3fv(newColor);
glWindowPos3fv(pos);

// next bitmaps
glCallList(c2);
glCallList(c3);
// etc.

As for performance, I suggest you try it and see if it’s fast enough for your needs.

Regarding your questions about centering text, multi-line text, etc. I understand the problem. If you use something like wglUseFontBitmaps() to generate the bitmaps, you don’t readily know how large each glyph is in order to do the placement computations. You’ll probably just have to use a Win32/GDI/whatever call to query the geometry of each glyph. Then work out the arithmetic.

There’s a number of OpenGL font/text utility libraries on the net.

-Brian