Search code examples
pythonopenglvbopyopenglvao

PyOpenGL cannot render any vao


I have spent almost 2-3 hours trying to figure out why I am not getting a rectangle renderered. I am using pygame for making a window, and opengl for rendering onto the window.

what should be happening is a red background with a blue rectangle, but what I am seeing is just the empty red background.

this is the code I used below.

am I uploading things to the shader wrong? or did I miss something.

import pygame
from pygame.locals import *
from OpenGL.GL import * 
from OpenGL.GLU import * 
import numpy as np
print("import sucessfull")

vertex = """
#version 460 core
layout (location=0) in vec3 position;

out vec4 fColor;

void main(){
    fColor = vec4(0,1,0,1);
    gl_Position = vec4(position, 1.0);
}
"""
fragment = """
#version 460 core
in vec4 fColor;
out vec4 color;
void main(){
    color = fColor;
    //gl_FragColor = fColor;
}
"""

def main():
    clock = pygame.time.Clock()
    pygame.init()
    display  = (800, 600)
    pygame.display.set_mode(display, DOUBLEBUF | OPENGL)
    gluPerspective(45, (display[0]/display[1]), 0.1, 1000)
    glClearColor(1, 0,0,1)
    glTranslatef(0,0,-5)

    #############################3
    vertexID = glCreateShader(GL_VERTEX_SHADER)
    glShaderSource(vertexID, vertex)
    fragmentID = glCreateShader(GL_FRAGMENT_SHADER)
    glShaderSource(fragmentID, fragment)
    glCompileShader(vertexID)
    glCompileShader(fragmentID)
    program = glCreateProgram()
    glAttachShader(program, vertexID)
    glAttachShader(program, fragmentID)
    glLinkProgram(program)

    positions = [
        0.5, -0.5, 0.0,
        -0.5, 0.5, 0.0,
        0.5, 0.5, 0.0,
        -0.5, -0.5, 0.0
    ]
    indexes = [
        2,1,0,
        0,1,3
    ]
    vao = glGenVertexArrays(1)
    glBindVertexArray(vao)
    vbo = glGenBuffers(1)
    glBindBuffer(GL_ARRAY_BUFFER, vbo)
    glBufferData(GL_ARRAY_BUFFER, np.array(positions, dtype=np.float32), GL_STATIC_DRAW)

    ebo = glGenBuffers(1)
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo)
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, np.array(indexes, dtype=np.float32), GL_STATIC_DRAW)

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 12, 0)
    glEnableVertexAttribArray(0)
    ################################

    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        #render here
        glUseProgram(program)
        glBindVertexArray(vao)
        glEnableVertexAttribArray(0)
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0)
        glDisableVertexAttribArray(0)
        glBindVertexArray(0)
        glUseProgram(0)
        #***********
        pygame.display.flip()
        clock.tick(40)

main()

Solution

  • The type of the indices must be integral and correspond to the type specified in the draw call (GL_UNSIGNED_INT). You have to create a NumPy array with the type uint32 instead of float32:

    glBufferData(GL_ELEMENT_ARRAY_BUFFER, np.array(indexes, dtype=np.float32), GL_STATIC_DRAW)

    glBufferData(GL_ELEMENT_ARRAY_BUFFER, np.array(indexes, dtype=np.uint32), GL_STATIC_DRAW)
    

    If a named buffer object is bound, then the 6th parameter of glVertexAttribPointer is treated as a byte offset into the buffer object's data store. But the type of the parameter is a pointer anyway (c_void_p).

    So if the offset is 0, then the 6th parameter can either be None or c_void_p(0) else the offset has to be caste to c_void_p(0):

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 12, 0)

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

    There is a similar problem with glDrawElements. The last argument is treated as a byte offset:

    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0)

    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, None)
    

    gluPerspective and glTranslatef set the deprecated fixed function pipeline matrices. This instructions do not make any sense when you use "modern" shader program. Remove this instructions. With modern OpenGL you have to use Uniform variables.