Визуализация одного символа в окне OpenGL (python) - PullRequest
1 голос
/ 18 марта 2020

С помощью следующего кода я хотел бы показать один символ в окне opengl, но все, что я получу, если символ будет напечатан несколько раз по горизонтали и вертикали небольшим размером в пространство, которое, как я полагаю, будет таким же большим, как персонаж должен быть. Спасибо.

Код (почти все):

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( )

1 Ответ

1 голос
/ 18 марта 2020

Изображение глифа, которое отображается библиотекой freetype, имеет только 1 цветной канал. Используйте GL_ALPHA для формата и внутреннего формата текстуры. См. glTexImage2D.
Далее вам нужно изменить параметр GL_UNPACK_ALIGNMENT. Параметр GL_UNPACK_ALIGNMENT определяет выравнивание первого пикселя в каждой строке (строке) изображения, когда изображение читается из буфера. По умолчанию этот параметр равен 4.
Каждый пиксель изображения глифа кодируется одним байтом, и изображение плотно упаковано. Таким образом, выравнивание изображения глифа равно 1, и параметр должен быть изменен до считывания изображения и указания текстуры:

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)

Поскольку вы не устанавливаете матрицу проекции, вы должны нарисовать геометрию в нормированном пространстве устройства. В нормализованном пространстве устройства все координаты находятся в ярости [-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()

Если вы хотите использовать координаты окна, вы должны установить проекцию orthographi c с помощью 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()

Полная функция makefont и 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)
...