I wrote the simple program below:
import pygame as pg
import moderngl as mgl
import sys
class GraphicsEngine:
def __init__(self, win_size=(1200,700)):
pg.init()
self.WIN_SIZE = win_size
pg.display.gl_set_attribute(pg.GL_CONTEXT_MAJOR_VERSION, 3)
pg.display.gl_set_attribute(pg.GL_CONTEXT_MINOR_VERSION, 3)
pg.display.gl_set_attribute(pg.GL_CONTEXT_PROFILE_MASK, pg.GL_CONTEXT_PROFILE_CORE)
pg.display.set_mode(self.WIN_SIZE, flags=pg.OPENGL | pg.DOUBLEBUF)
self.ctx = mgl.create_context()
self.clock = pg.time.Clock()
def check_events(self):
for event in pg.event.get():
if event.type == pg.QUIT or (event.type == pg.KEYDOWN and event.key == pg.K_ESCAPE):
pg.quit()
sys.exit()
def render(self):
self.ctx.clear(color=(0.08, 0.16, 0.18))
pg.display.flip()
def run(self):
while True:
self.check_events()
self.render()
self.clock.tick(60)
pg.display.set_caption(pg.time.get_fps())
if __name__ == '__main__':
app=GraphicsEngine()
app.run()
and I get this error
File "path\main.py", line 41, in <module>
app=GraphicsEngine()
^^^^^^^^^^^^^^^^
File "path\main.py", line 16, in __init__
self.ctx = mgl.create_context()
^^^^^^^^^^^^^^^^^^^^
File "C:\Users\\AppData\Roaming\Python\Python311\site->packages\moderngl\context.py", line 1968, in create_context
ctx.mglo, ctx.version_code = >mgl.create_context(glversion=require, mode=mode, **settings)
>^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\\AppData\Roaming\Python\Python311\site->packages\glcontext\__init__.py", line 69, in create
return wgl.create_context(**kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Exception: cannot detect OpenGL context
I tried to reinstall moderngl but nothing changed
Let's start at the end of your traceback:
Looking in
__init__.py, we don't find the string"cannot detect OpenGL context". But, on line 56, we do find:In
moderngl's source code, we find a filewgl.cpp, with the lines (119–123):I don't know what
res->hrcis, but nor do I need to, because it's the return value ofres->m_wglGetCurrentContext(), and that function comes from line 80:A little earlier (line 73), we see that
res->libglis:where
libglis (line 50):So there's a problem with the
wglGetCurrentContextfunction fromopengl32.dll. Let's check Microsoft's Win32API documentation:The
!res->hrcon line 120 is checking forNULL, so this looks like our culprit!Now, why is there no OpenGL rendering context...?
Standalone hypothesis
The Windows API documentation tells us how to create an OpenGL context – and, indeed, there's a function
res->m_wglCreateContextinwgl.cpp. It's called on line 214, inside anifblock starting at line 180:Where does
modecome from? Lines 49–55:It looks hardcoded… but it doesn't look like it's supposed to be. Let's check the Python documentation for
PyArg_ParseTupleAndKeywords:Not terribly useful, but Stack Overflow yields some code examples and, put together, we can see that
modeis a bog-standard Python kwarg.So, following the keyword arguments up the traceback, consulting the source code of each function, we find that changing your line 16:
to:
fixes the immediate problem: now an OpenGL context is created. However, it doesn't seem to do anything.
Pygame hypothesis
The ModernGL documentation says:
As Rabbid76 identified, ModernGL is supposed to pick up the context from
pygame. The fact it doesn't is curious. They should be created bypygame.init(), so let's track that down.So
pygame.initis defined in C – as one might expect.base.c'spg_inithas an identical function and an identical return type, so I'll assume that's it. Lines 341–343:Lines 361–368:
pgmod_autoinitlooks for a function named_internal_mod_initand, failing that, a function calledinit. Thepygame.displaymodule handles SDL2, which handles OpenGL contexts;display._internal_mod_initdoesn't exist, butpygame.display.initdoes. The relevant section:(
return NULL;means an exception occurred, and it should be re-raised.)SDL2's code is pretty solid, so there's probably no bug there. However, recall the code from
base.c: if this code fails,pygame.init()will swallow the exception, and the only way you'd know anything went wrong is if you checked the return value.It's probably possible to debug this further by looking into SDL2's source code, to find the conditions under which
wglCreateContextdoesn't get called, but the easiest way would be to checkpygame.init()'s return value.