There are many ways for displaying text in OpenGL. In this post, I'll use the glutBitmapCharacter function to draw characters, and then will extend it to a more generic function (printw
), which will make drawing a string in OpenGL as simple as using printf
.
First, I will start by defining the font to be used by the glutBitmapCharacter
function. I will choose a 24-point proportional spaced Times Roman font as shown below:
GLvoid *font_style = GLUT_BITMAP_TIMES_ROMAN_24;
To draw a character, simply define the raster position using glRasterPos3f (x, y, z), then draw it using glutBitmapCharacter(font_style, character). To extend this to drawing a string at certain coordinates, loop over each character in the string and draw it with glutBitmapCharacter. The additional logic that goes below is in making this as pretty as printf
.
This can be done by using C’s va_list type, which is C’s approach to defining functions with variables number of arguments.
- In the function prototype, place ellipsis (…) as the last argument
- Define a variable argument list: va_list args;
- Call
va_start
on the args list and the first real argument in the function prototype preceding the ellipsis: va_start(args, format); - Use _vscprintf to get the number of characters that would be generated if the string pointed to by the list of arguments was printed using the specified format
- Allocate memory for a string with the specified number of characters
- Call vsprintf_s to build the string we want from the list of arguments
- Call va_end to end the use of the variables argument list
- Draw our beautified string
- Free allocated memory
Function implementation with full comments are shown below:
void printw (float x, float y, float z, char* format, ...)
{
va_list args; int len; int i; char * text;
va_start(args, format);
len = _vscprintf(format, args) + 1;
text = malloc(len * sizeof(char));
vsprintf_s(text, len, format, args);
va_end(args);
glRasterPos3f (x, y, z);
for (i = 0; text[i] != '\0'; i++)
glutBitmapCharacter(font_style, text[i]);
free(text);
}
Now that printw
is defined, using it is similar to printf
:
printf( "char: %c, decimal: %d, float: %f,
string: %s", 'X', 1618, 1.618, "text");
printw(x, y, z, "char: %c, decimal: %d, float: %f,
string: %s", 'X', 1618, 1.618, "text");
Libraries to include before copying the function are:
#include <stdio.h> // Standard Input\Output C Library
#include <stdarg.h> // To use functions with variables arguments
#include <stdlib.h> // for malloc
#include <gl/glut.h> // Include GLUT, OpenGL, and GLU libraries
Here is the sample code that contains the printw
function. If you have any issues compiling or running the app, check out this section for details about compiling and running an OpenGL app that uses the GLUT library. Below is a screen shot of the demo app:
Filed under: C, OpenGL Tagged: glRasterPos, glutBitmapCharacter, GLUT_BITMAP_HELVETICA, GLUT_BITMAP_TIMES_ROMAN, OpenGL string, OpenGL Text, printw, va_end, va_list, va_start, vsprintf_s, _vscprintf