Reputation: 73
With the following code I'd like to show a single character in an opengl window, but all I get if the character printed multiple time orizontally and vertically in small sizer into a space that is, I presume, as large as the character should be. Thank you.
The code (almost all):
import numpy
from freetype import *
import OpenGL.GL as gl
import OpenGL.GLUT as glut
text = 'H'
def makefont(filename, size):
face = Face(filename)
face.set_char_size( size*64 )
face.load_char(text, FT_LOAD_RENDER | FT_LOAD_FORCE_AUTOHINT)
bitmap = face.glyph.bitmap
data = bitmap.buffer
rows = bitmap.rows
width = bitmap.width
ascender = face.glyph.bitmap_top
descender = bitmap.rows-face.glyph.bitmap_top
height = ascender+descender
imageData = numpy.array(bitmap.buffer, numpy.uint8).reshape(rows,width)
imageData = imageData[::-1,:]
#########
textureID = gl.glGenTextures(1)
gl.glBindTexture( gl.GL_TEXTURE_2D, textureID )
gl.glTexParameterf( gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR )
gl.glTexParameterf( gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR )
gl.glTexImage2D( gl.GL_TEXTURE_2D, 0, gl.GL_RGBA, width, height, 0,
gl.GL_RGBA, gl.GL_UNSIGNED_BYTE, imageData )
#
gl.glBindTexture(gl.GL_TEXTURE_2D, textureID)
gl.glBegin(gl.GL_QUADS)
gl.glTexCoord2f(0, 0)
x = 0
y = 0
w = width
h = height
gl.glVertex2f(x, y)
gl.glTexCoord2f(1, 0)
gl.glVertex2f(x + w, y)
gl.glTexCoord2f(1, 1)
gl.glVertex2f(x + w, y + h)
gl.glTexCoord2f(0, 1)
gl.glVertex2f( x, y + h)
gl.glEnd()
def on_display( ):
gl.glClearColor(1,1,1,1)
gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)
gl.glColor(0,0,0,1)
makefont( './VeraMono.ttf', 64 )
glut.glutSwapBuffers( )
def on_reshape( width, height ):
#
if __name__ == '__main__':
import sys
glut.glutInitDisplayMode( glut.GLUT_DOUBLE | glut.GLUT_RGB | glut.GLUT_DEPTH )
gl.glTexEnvf( gl.GL_TEXTURE_ENV, gl.GL_TEXTURE_ENV_MODE, gl.GL_MODULATE )
gl.glEnable( gl.GL_DEPTH_TEST )
gl.glEnable( gl.GL_BLEND )
gl.glEnable( gl.GL_COLOR_MATERIAL )
gl.glColorMaterial( gl.GL_FRONT_AND_BACK, gl.GL_AMBIENT_AND_DIFFUSE )
gl.glBlendFunc( gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA )
gl.glEnable( gl.GL_TEXTURE_2D )
glut.glutMainLoop( )
Upvotes: 1
Views: 373
Reputation: 210996
The glyph image which is rendered by the freetype library has just 1 color channel. Use GL_ALPHA
for the format and internal format of the texture. See glTexImage2D
.
Further more you have to change the GL_UNPACK_ALIGNMENT
parameter.
The GL_UNPACK_ALIGNMENT
parameter defines the alignment of the first pixel in each row (line) of an image when the image is read form the buffer. By default the this parameter is 4.
Each pixel of the glyph image is encoded in one byte and the image is tightly packed. So the the alignment of the glyph image is 1 and the parameter has to be changed before the image is read and the texture is specified:
gl.glPixelStorei(gl.GL_UNPACK_ALIGNMENT, 1)
gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_ALPHA, width, height, 0,
gl.GL_ALPHA, gl.GL_UNSIGNED_BYTE, imageData)
Since you do not set any projection matrix, you have to draw the geometry in normalized device space. In normalized device space all the coordinates are in rage [-1.0, 1.0]:
x, y, w, h = -1, -1, 2, 2
gl.glBegin(gl.GL_QUADS)
gl.glTexCoord2f(0, 0)
gl.glVertex2f(x, y)
gl.glTexCoord2f(1, 0)
gl.glVertex2f(x + w, y)
gl.glTexCoord2f(1, 1)
gl.glVertex2f(x + w, y + h)
gl.glTexCoord2f(0, 1)
gl.glVertex2f( x, y + h)
gl.glEnd()
If you want to use window coordinates, the you have to set an orthographic projection by glOrtho
:
gl.glMatrixMode(gl.GL_PROJECTION)
gl.glLoadIdentity()
gl.glOrtho(0, width, height, 0, -1, 1)
gl.glMatrixMode(gl.GL_MODELVIEW)
x, y, w, h = 0, 0, width, height
gl.glBegin(gl.GL_QUADS)
gl.glTexCoord2f(0, 0)
gl.glVertex2f(x, y)
gl.glTexCoord2f(1, 0)
gl.glVertex2f(x + w, y)
gl.glTexCoord2f(1, 1)
gl.glVertex2f(x + w, y + h)
gl.glTexCoord2f(0, 1)
gl.glVertex2f( x, y + h)
gl.glEnd()
Complete function makefont
and on_reshape
:
def makefont(filename, size):
face = Face(filename)
face.set_char_size( size*64 )
face.load_char(text, FT_LOAD_RENDER | FT_LOAD_FORCE_AUTOHINT)
bitmap = face.glyph.bitmap
data = bitmap.buffer
rows = bitmap.rows
width = bitmap.width
ascender = face.glyph.bitmap_top
descender = bitmap.rows-face.glyph.bitmap_top
height = ascender+descender
imageData = numpy.array(bitmap.buffer, numpy.uint8).reshape(rows,width)
imageData = imageData[::-1,:]
textureID = gl.glGenTextures(1)
gl.glBindTexture( gl.GL_TEXTURE_2D, textureID )
gl.glTexParameterf( gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR )
gl.glTexParameterf( gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR )
gl.glPixelStorei(gl.GL_UNPACK_ALIGNMENT, 1)
gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_ALPHA, width, height, 0,
gl.GL_ALPHA, gl.GL_UNSIGNED_BYTE, imageData)
x, y, w, h = 0, 0, width, height
gl.glBindTexture(gl.GL_TEXTURE_2D, textureID)
gl.glBegin(gl.GL_QUADS)
gl.glTexCoord2f(0, 0)
gl.glVertex2f(x, y)
gl.glTexCoord2f(1, 0)
gl.glVertex2f(x + w, y)
gl.glTexCoord2f(1, 1)
gl.glVertex2f(x + w, y + h)
gl.glTexCoord2f(0, 1)
gl.glVertex2f( x, y + h)
gl.glEnd()
def on_reshape( width, height ):
gl.glViewport(0, 0, width, height)
gl.glMatrixMode(gl.GL_PROJECTION)
gl.glLoadIdentity()
gl.glOrtho(0, width, height, 0, -1, 1)
gl.glMatrixMode(gl.GL_MODELVIEW)
See also Immediate mode and legacy OpenGL
Upvotes: 1