pythonopenglpygameglslpyopengl

Trying to get PyOpenGL Shaders to Work (Only White Screen Appearing); Maybe Vertex Wrong?


I attempted to use a pygame font surface and converting it to pixel data using data = pygame.image.tostring(img, "RGBA", 1) and then used a gl function to create an opengl texture and draw it with glDrawArrays using shaders too. However, the results are simply a white screen without any text.

Here is the code I attempted:

from __future__ import division
import pygame
import numpy as np
from OpenGL.GL import *
from OpenGL.GL import shaders
from pygame import *

pygame.init()
screen = pygame.display.set_mode((600, 400), DOUBLEBUF | OPENGL)

vertex_shader = shaders.compileShader("""
#version 130

in vec3 position;
out vec2 fragTexCoord;
uniform mat4 projectionMatrix;
uniform mat4 modelViewMatrix;

void main() {
  gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
  fragTexCoord = gl_Position.xy;
}
""", GL_VERTEX_SHADER)

fragment_shader = shaders.compileShader("""
#version 130

in vec2 fragTexCoord;
uniform sampler2D textureSampler;

out vec4 fragmentColor;

void main() {
  fragmentColor = texture(textureSampler, fragTexCoord);
}
""", GL_FRAGMENT_SHADER)
shader_program = shaders.compileProgram(vertex_shader, fragment_shader)

img = pygame.font.Font(None, 50).render("Hello", True, (255, 255, 255))
w, h = img.get_size()
texture = glGenTextures(1)
glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
glBindTexture(GL_TEXTURE_2D, texture)
glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
data = pygame.image.tostring(img, "RGBA", 1)
glTexImage2D(GL_TEXTURE_2D, 0, 4, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data)

quad_vertices = np.array([
    [-1.0, -1.0, 0.0],
    [ 1.0, -1.0, 0.0],
    [ 1.0,  1.0, 0.0],
    [-1.0,  1.0, 0.0],
], dtype=np.float32)


projection_matrix_loc = glGetUniformLocation(shader_program, "projectionMatrix")
modelview_matrix_loc = glGetUniformLocation(shader_program, "modelViewMatrix")

projection_matrix = np.array([[1.0, 0.0, 0.0, 0.0],
                              [0.0, 1.0, 0.0, 0.0],
                              [0.0, 0.0, -1.0, -1.0],
                              [0.0, 0.0, -1.0, 1.0]], dtype=np.float32)
modelview_matrix = np.identity(4, dtype=np.float32)

while True:
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            exit()

    glClear(GL_COLOR_BUFFER_BIT)

    glUseProgram(shader_program)

    glUniformMatrix4fv(projection_matrix_loc, 1, GL_FALSE, projection_matrix)
    glUniformMatrix4fv(modelview_matrix_loc, 1, GL_FALSE, modelview_matrix)

    VBO = glGenBuffers(1)
    glBindBuffer(GL_ARRAY_BUFFER, VBO)
    glBufferData(GL_ARRAY_BUFFER, quad_vertices.size * quad_vertices.dtype.itemsize, quad_vertices, GL_STATIC_DRAW)

    glEnableVertexAttribArray(0)
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, None)

    glBindTexture(GL_TEXTURE_2D, texture)

    glDrawArrays(GL_TRIANGLE_FAN, 0, 4)

    glUseProgram(0)

    pygame.display.flip()
    pygame.time.Clock().tick(60)

Solution

  • You must set the background color when you render the text:

    flont = pygame.font.Font(None, 50)
    img = font.render("Hello", True, (255, 255, 255), (0, 0, 0))
    

    See also pygame + opengl = display text