How to Draw Text with Glut/Opengl in C++

How do I draw text with GLUT / OpenGL in C++?

There are two ways to draw strings with GLUT

glutStrokeString will draw text in 3D

alt text
(source: uwa.edu.au)

and glutBitmapString will draw text facing the user

alt text
(source: sourceforge.net)

using glutBitmapCharacter() to draw text closing opengl program

If you want to use any function of the GLUT library, then GLUT has to be initialized by glutInit. e.g.:

int main(int argc, char** argv)
{
glutInit(&argc, argv);

// [...]
}

Using GLUT to simply print text

You don't say what's specifically wrong, but I'm suspecting that your text is not showing up. The reason is likely that the raster position is being clipped, and this is causing your text to not be rendered.

The raster position is the "anchor point" of where a bitmap will be drawn. Usually, this is the lower-left corner of the bitmap (the glBitmap can change that with by setting the x and y parameters to something other than zero, but assume you're not doing that). The raster position is transformed by the model-view matrix, just like a vertex in a geometric primitive. And just like a vertex, if the transformed raster position lies outside of the viewport, it's clipped, and nothing is rendered. What's important to know here is that any rendering of a bitmap - regardless of its size - is predicated on the raster position being inside of the viewport.

In your example, you don't show the viewport you're using, nor the projection transformation (the matrix on the GL_PROJECTION stack), but you set the raster position to (1280, 720), which may well be outside of the viewport.

Let's say you want to render your text in the lower-left corner of your window (and for the sake of argument, let's say your window is 1280 x 1024). When it's time to render your text, drop the following into your rendering routine:

glMatrixMode( GL_PROJECTION );
glPushMatrix();
glLoadIdentity();
gluOrtho2D( 0, 1280, 0, 1024 );

glMatrixMode( GL_MODELVIEW );
glPushMatrix();
glLoadIdentity();
glRasterPos2i( 10, 1014 ); // move in 10 pixels from the left and bottom edges
for ( int i = 0; i < len; ++i ) {
glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_10, menu[i]);
}
glPopMatrix();

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

Depending on which version of OpenGL you're using, you may be able to use a simpler routine glWindowPos2i() (the 2i can be replaced with other dimension-type pairs like other OpenGL functions), which bypasses transforming the raster position by the model-view and projection matrices, and works directly in window coordinates. In that case, you'd write the above code as:

glWindowPos2i( 10, 1014 );  // move in 10 pixels from the left and bottom edges
for ( int i = 0; i < len; ++i ) {
glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_10, menu[i]);
}

How to display text over rectangle in OpenGL in C++?

Okay after a day I got it, I'm so dumb :')

#ifdef __APPLE_CC__
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif

void init2D(float r, float g, float b)
{
glClearColor(r, g, b, 0.0);
glMatrixMode(GL_PROJECTION);
gluOrtho2D(0.0, 600.0, 0.0, 600.0);
}

void rectangle()
{
glBegin(GL_POLYGON);
glColor3f(0.4,0,0.8);
glVertex3f(150.0f, 200.0f, 0.0f);
glColor3f(0.4,0,0.8);
glVertex3f(450.0f, 200.0f, 0.0f);
glColor3f(0.6,0,0.6);
glVertex3f(450.0f, 400.0f, 0.0f);
glColor3f(0.6,0,0.6);
glVertex3f(150.0f, 400.0f, 0.0f);
glEnd();
}

void text()
{
char menu[80];
strcpy(menu,"Have courage and be kind");
int len;
len = strlen(menu);

glColor3f(1,1,1);

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

gluOrtho2D( 0, 600, 0, 600 );

glMatrixMode( GL_MODELVIEW );
glPushMatrix();

glLoadIdentity();

glRasterPos2i(190, 300);

for ( int i = 0; i < len; ++i )
{
glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, menu[i]);
}

glPopMatrix();

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

void display()
{

glClear(GL_COLOR_BUFFER_BIT);

rectangle();
text();

glFlush();
}

int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);

glutInitWindowPosition(0, 0);
glutInitWindowSize(600, 600);
glutCreateWindow("Assignment 1 Question 2");
init2D(0.0f, 0.0f, 0.0f);
glutDisplayFunc(display);

glutMainLoop();
}

opengl display shape and draw text

Try this:

#include <GL/glut.h>

GLfloat g_xeye;
GLfloat g_yeye;

bool rollOn;

GLfloat g_light_position[] = {0.0, 10.0, 10.0, 0.0};

void timer( int extra )
{
if (rollOn){
g_xeye = g_xeye + 00000.1;
g_yeye = g_yeye + 00000.1;
}
glutTimerFunc( 16, timer, 0 );
glutPostRedisplay();
}

void drawBitmapText(char *string, float x, float y, float z)
{
char *c;
glRasterPos3f(x, y, z);

for (c=string; *c != '\0'; c++)
{
glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_10, *c);
}
}

void display(void)
{
glClearColor (0.0, 0.0, 0.0, 0.0);
glClear (GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT);

// draw cube in 3D
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
double w = glutGet( GLUT_WINDOW_WIDTH );
double h = glutGet( GLUT_WINDOW_HEIGHT );
gluPerspective(60, w / h, 1.0, 100.0);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0, 0, 6, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

glPushMatrix();
glRotatef(g_xeye, 1, 0, 0);
glRotatef(g_yeye, 0, 1, 0);
GLfloat redDiffuseMaterial[] = {0.50, 0.0, 0.50, 0.0};
glMaterialfv(GL_FRONT, GL_DIFFUSE, redDiffuseMaterial);
glutSolidCube(2.0);
glPopMatrix();

// switch to 2D for text overlay
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho( 0, w, 0, h, -1, 1 );

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

glDisable( GL_LIGHTING );
glColor3ub(255,255,255);
drawBitmapText("Hello world",200,200,0);
glEnable( GL_LIGHTING );

glutSwapBuffers ();
}

void keyboard(unsigned char key, int x, int y)
{
if (key==27)
exit(0);
if (key == ',')
{
g_light_position[0] = g_light_position[0] - 1;
}
if (key == '.')
{
g_light_position[0] = g_light_position[0] + 1;
glLightfv(GL_LIGHT0, GL_POSITION, g_light_position);
}
if (key==32)
{
rollOn = !rollOn;
}
}

void special(int key, int x, int y)
{
if (key==27)
exit(0);
if (key == GLUT_KEY_UP)
{
g_xeye = g_xeye + 2;
}
if (key == GLUT_KEY_DOWN)
{
g_xeye = g_xeye - 2;
}
if (key == GLUT_KEY_RIGHT)
{
g_yeye = g_yeye + 2;
}
if (key == GLUT_KEY_LEFT)
{
g_yeye = g_yeye - 2;
}
}

void init(void)
{
glEnable(GL_DEPTH_TEST);

glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);

glLightfv(GL_LIGHT0, GL_POSITION, g_light_position);

rollOn = false;

g_xeye = 0;
g_yeye = 0;
}

int main(int argc, char** argv)
{
glutInit( &argc, argv );
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(500,500);
glutInitWindowPosition(100, 100);
glutCreateWindow ("Project");
init();

glutKeyboardFunc(keyboard);
glutSpecialFunc(special);
glutDisplayFunc(display);
glutTimerFunc( 0, timer, 0 );
glutMainLoop();
return 0;
}

You can avoid the 2D switch if you're willing to use glWindowPos() from OpenGL 1.4 instead of glRasterPos().

Text on screen with GLUT

Is it possible without Freeglut.h?

Yup. glutBitmapCharacter() and glutStrokeCharacter() are both in the regular glut.h.

freeglut.h just adds glutBitmapHeight()/glutBitmapString() and their stroked equivalents.


EDIT: How do I implement it into a loop?

The straightforward way:

void MyBitmapString( void* font, const std::string& str )
{
for( size_t i = 0; i < str.size(); ++i )
{
glutBitmapCharacter( font, (int)str[i] );
}
}

Use glRasterPos() or glWindowPos() for positioning.



Related Topics



Leave a reply



Submit