Search code examples
pythonopenglpyqtshaderpyopengl

Can't compile shader without glfw context


I am trying to compile OpenGL shaders using the Python bindings. I can not compile them without creating a glfw context, it is quite strange. If you uncomment the glfw lines, the shaders will get compiled. print(bool(glCreateShader)) outputs False.

Error:

Traceback (most recent call last):
  File "C:\Program Files\Python38\lib\site-packages\OpenGL\latebind.py", line 43, in __call__
    return self._finalCall( *args, **named )
TypeError: 'NoneType' object is not callable

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:/Users/reas/Desktop/Programación/OpenGeEle/Moderno.py", line 44, in <module>
    shader = compileShader(vertex_src, GL_VERTEX_SHADER)
  File "C:\Program Files\Python38\lib\site-packages\OpenGL\GL\shaders.py", line 228, in compileShader
    shader = glCreateShader(shaderType)
  File "C:\Program Files\Python38\lib\site-packages\OpenGL\latebind.py", line 46, in __call__
    self._finalCall = self.finalise()
  File "C:\Program Files\Python38\lib\site-packages\OpenGL\extensions.py", line 242, in finalise
    raise error.NullFunctionError(
OpenGL.error.NullFunctionError: Attempt to call an undefined alternate function (glCreateShader, glCreateShaderObjectARB), check for bool(glCreateShader) before calling

Process finished with exit code 1

Source code:

import numpy as np
from numpy import array
from OpenGL.GL import (GL_ARRAY_BUFFER, GL_COLOR_BUFFER_BIT, GL_FRAGMENT_SHADER, GL_STATIC_DRAW,
                       GL_VERTEX_SHADER, glBindBuffer, glBufferData, glClear, glClearColor,
                       glGenBuffers)
from OpenGL.GL.shaders import compileShader, compileProgram
from PyQt5.QtWidgets import QApplication, QMainWindow, QOpenGLWidget

# IF I UNCOMMENT THIS, THE SHADERS WORK
"""
import glfw

glfw.init()
window = glfw.create_window(1280, 720, "My OpenGL window", None, None)
glfw.make_context_current(window)
"""

vertex_src = """
# version 330

in vec3 a_position;
in vec3 a_color;

out vec3 v_color;

void main()
{
    gl_Position = vec4(a_position, 1.0);
    v_color = a_color;
}
"""

fragment_src = """
# version 330

in vec3 v_color;
out vec4 out_color;

void main()
{
    out_color = vec4(v_color, 1.0);
}
"""

shader = compileShader(vertex_src, GL_VERTEX_SHADER)
shader2 = compileShader(fragment_src, GL_FRAGMENT_SHADER)
programa = compileProgram(shader, shader2)

Solution

  • For any OpenGL instruction a current and valid OpenGL Context is required. QOpenGLWidget creates and provides an OpenGL context, but the context is only made current before the initializeGL, paintGL respectively resizeGL callback.
    Hence you have to move the code, which creates and compiles the shader, in the initializeGL event callback method.