Print text with glut and python
Question:
I’ve written this function for printing some text with python and python opengl
def glut_print( x, y, font, text, r, g , b , a):
blending = False
if glIsEnabled(GL_BLEND) :
blending = True
#glEnable(GL_BLEND)
glColor3f(1,1,1)
glRasterPos2f(x,y)
for ch in text :
glutBitmapCharacter( font , ctypes.c_int( ord(ch) ) )
if not blending :
glDisable(GL_BLEND)
And the rendering function:
def Draw():
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT )
glut_print( 10 , 10 , GLUT_BITMAP_9_BY_15 , "Hallo World" , 1.0 , 1.0 , 1.0 , 1.0 )
# draw my scene ......
glutSwapBuffers()
As a result nothing is written, I’m viewing my geometric and 3D objects; but not the text!
Where’s the problem?
Answers:
A lot of OpenGL programmers get caught by this (myself included).
Although glRasterPos looks like it takes pixel coordinates, they are actually transformed by the modelview and projection matrices before use. Useful if you’re trying to position text in 3D space, not so useful when you want some kind of overlay console or HUD.
The old way to get around this was to push both projection and modelview matrices, set both to identity, draw text, pop both.
Brian Paul of Mesa3D thought this was silly and added a new call glWindowPos which takes actual pixel coordinates in the window. It became standard in OpenGL 1.4 or so. Replace your glRasterPos with glWindowPos and see if that fixes the problem.
I’ve solved by switching projection like this:
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluOrtho2D(0.0, 1.0, 0.0, 1.0)
glMatrixMode(GL_MODELVIEW)
glut_print( 10 , 10 , GLUT_BITMAP_9_BY_15 , "Hallo World" , 1.0 , 1.0 , 1.0 , 1.0 )
And after the print I go back to the common 3D model.
@ Hug … I’l try also the glWindowPos
use gultStrokeCharacter is better, the character can be rotated and scaled since it draws lines to form the character.
Another solution (based on @Hugh answer and on version PyOpenGL 3.1.6):
class TextView():
def __init__(self, x, y, color):
self.x= x
self.y=y
self.color= color
def print(self, text):
glColor3fv(self.color)
glPushMatrix();
glWindowPos2f(self.x, self.y)
for ch in text :
glutBitmapCharacter( GLUT_BITMAP_TIMES_ROMAN_24 , ctypes.c_int( ord(ch) ) )
glPopMatrix();
Additionally for Ubuntu 22.04 I had to
sudo apt install libosmesa6 freeglut3-dev
and do
import os
os.environ['PYOPENGL_PLATFORM'] = 'osmesa'
before importing OpenGL.GLUT
in your .py file
I’ve written this function for printing some text with python and python opengl
def glut_print( x, y, font, text, r, g , b , a):
blending = False
if glIsEnabled(GL_BLEND) :
blending = True
#glEnable(GL_BLEND)
glColor3f(1,1,1)
glRasterPos2f(x,y)
for ch in text :
glutBitmapCharacter( font , ctypes.c_int( ord(ch) ) )
if not blending :
glDisable(GL_BLEND)
And the rendering function:
def Draw():
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT )
glut_print( 10 , 10 , GLUT_BITMAP_9_BY_15 , "Hallo World" , 1.0 , 1.0 , 1.0 , 1.0 )
# draw my scene ......
glutSwapBuffers()
As a result nothing is written, I’m viewing my geometric and 3D objects; but not the text!
Where’s the problem?
A lot of OpenGL programmers get caught by this (myself included).
Although glRasterPos looks like it takes pixel coordinates, they are actually transformed by the modelview and projection matrices before use. Useful if you’re trying to position text in 3D space, not so useful when you want some kind of overlay console or HUD.
The old way to get around this was to push both projection and modelview matrices, set both to identity, draw text, pop both.
Brian Paul of Mesa3D thought this was silly and added a new call glWindowPos which takes actual pixel coordinates in the window. It became standard in OpenGL 1.4 or so. Replace your glRasterPos with glWindowPos and see if that fixes the problem.
I’ve solved by switching projection like this:
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluOrtho2D(0.0, 1.0, 0.0, 1.0)
glMatrixMode(GL_MODELVIEW)
glut_print( 10 , 10 , GLUT_BITMAP_9_BY_15 , "Hallo World" , 1.0 , 1.0 , 1.0 , 1.0 )
And after the print I go back to the common 3D model.
@ Hug … I’l try also the glWindowPos
use gultStrokeCharacter is better, the character can be rotated and scaled since it draws lines to form the character.
Another solution (based on @Hugh answer and on version PyOpenGL 3.1.6):
class TextView():
def __init__(self, x, y, color):
self.x= x
self.y=y
self.color= color
def print(self, text):
glColor3fv(self.color)
glPushMatrix();
glWindowPos2f(self.x, self.y)
for ch in text :
glutBitmapCharacter( GLUT_BITMAP_TIMES_ROMAN_24 , ctypes.c_int( ord(ch) ) )
glPopMatrix();
Additionally for Ubuntu 22.04 I had to
sudo apt install libosmesa6 freeglut3-dev
and do
import os
os.environ['PYOPENGL_PLATFORM'] = 'osmesa'
before importing OpenGL.GLUT
in your .py file