[Python] Why can I not create a vertex array with ModernGL?

Discussão em 'Python' iniciado por Stack, Agosto 4, 2025.

  1. Stack

    Stack Membro Participativo

    I'm trying to make a game with pygame, and I'm using moderngl to use shaders. However, I'm getting constant issues trying to create moderngl objects. Currently, I cannot create multiple moderngl Vertex Arrays. It's weird, I'm able to create one but when I go to create the second or third the code returns a moderngl Error. I'm new to ModernGL so it could be a simple issue that I'm not seeing.

    Here's my shader manager that manages the loading and post_processing of shaders:

    class ShaderManager:
    def __init__(self, ctx: moderngl.Context, initial_size: tuple[int,int]):
    self.ctx = ctx
    # 1 quad VBO (x,y) + (u,v)
    verts = np.array([
    -1, 1, 0.0, 0.0,
    -1, -1, 0.0, 1.0,
    1, 1, 1.0, 0.0,
    1, -1, 1.0, 1.0,
    ], dtype='f4')
    self.quad_vbo = ctx.buffer(verts.tobytes())

    self.programs: dict[str, moderngl.Program] = {}
    self.vaos: dict[str, moderngl.VertexArray] = {}
    self.fbo_cache: dict[tuple[int,int], tuple] = {}

    # pre-allocate initial FBO textures
    self._ensure_fbo(initial_size)

    def load(self, name: str, vert_source: str | Path, frag_source: str | Path):
    """Compile and register a shader program from file paths or raw source strings."""
    if isinstance(vert_source, Path) or isinstance(vert_source, str) and Path(vert_source).exists():
    vs = Path(vert_source).read_text(encoding='utf-8')
    else:
    vs = vert_source # treat as raw GLSL string

    if isinstance(frag_source, Path) or isinstance(frag_source, str) and Path(frag_source).exists():
    fs = Path(frag_source).read_text(encoding='utf-8')
    else:
    fs = frag_source # treat as raw GLSL string

    prog = self.ctx.program(vertex_shader=vs, fragment_shader=fs)
    self.programs[name] = prog

    def _ensure_fbo(self, size: tuple[int,int]):
    """Make textures+FBO for this resolution if missing."""
    if size in self.fbo_cache:
    return
    w,h = size
    in_tex = self.ctx.texture((w,h), 4, alignment=1)
    out_tex = self.ctx.texture((w,h), 4, alignment=1)
    for t in (in_tex, out_tex):
    t.filter = (moderngl.NEAREST, moderngl.NEAREST)
    t.swizzle = 'BGRA'
    fbo = self.ctx.framebuffer(color_attachments=[out_tex])
    self.fbo_cache[size] = (in_tex, out_tex, fbo)

    def _get_vao(self, name: str):
    """Lazily create a VAO that feeds quad_vbo into in_vert/in_uv."""
    if name not in self.vaos:
    prog = self.programs[name]
    # Explicitly tell moderngl how the VBO is structured: 2 floats (pos), 2 floats (uv)
    vao = self.ctx.vertex_array(
    prog,
    [(self.quad_vbo, '2f 2f', 'in_vert', 'in_uv')]
    )
    self.vaos[name] = vao
    return self.vaos[name]

    def post_process(self, passes: list[str], scene: pygame.Surface) -> pygame.Surface:
    """
    Run each named pass in order over `scene`, returning the final.
    Internally uses two ping-pong FBOs sized to scene.get_size().
    """
    size = scene.get_size()
    self._ensure_fbo(size)
    in_tex, out_tex, fbo = self.fbo_cache[size]

    # upload initial
    data = pygame.image.tostring(scene, 'RGBA', False)
    in_tex.write(data)
    in_tex.use(location=0)

    current_tex = in_tex
    for name in passes:
    prog = self.programs[name]
    # bind
    prog['tex'].value = 0
    if 'time' in prog:
    prog['time'].value = time.time() % 1000

    # render into out_tex
    fbo.use()
    self.ctx.clear(0.0,0.0,0.0,1.0)
    vao = self._get_vao(name)
    vao.render(mode=moderngl.TRIANGLE_STRIP)

    # swap
    current_tex, out_tex = out_tex, current_tex
    fbo = self.ctx.framebuffer(color_attachments=[out_tex])
    out_tex.use(location=0)

    # readback final
    final_data = current_tex.read()
    return pygame.image.frombuffer(final_data, size, 'RGBA')


    However, it's returning the following error:

    PS C:\Users\infamoose\Documents\coding\spellsmithAgain> python main.py
    pygame 2.6.1 (SDL 2.28.4, Python 3.11.9)
    Hello from the pygame community. https://www.pygame.org/contribute.html
    Traceback (most recent call last):
    File "C:\Users\infamoose\Documents\coding\spellsmithAgain\main.py", line 39, in <module>
    run_game()
    File "C:\Users\infamoose\Documents\coding\spellsmithAgain\main.py", line 35, in run_game
    instanceManager(screen, settingsManager(), ctx)
    File "C:\Users\infamoose\Documents\coding\spellsmithAgain\utility\instanceManager.py", line 39, in __init__
    main_menu(screen, self)
    File "C:\Users\infamoose\Documents\coding\spellsmithAgain\screens\main_menu.py", line 184, in main_menu
    base.run()
    File "C:\Users\infamoose\Documents\coding\spellsmithAgain\utility\screen_utility\baseScreen.py", line 271, in run
    self.draw(virtual_mouse)
    File "C:\Users\infamoose\Documents\coding\spellsmithAgain\utility\screen_utility\baseScreen.py", line 246, in draw
    surf = sm.post_process(["invert", "blur"], surf)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "C:\Users\infamoose\Documents\coding\spellsmithAgain\utility\shaderManager.py", line 93, in post_process
    vao = self._get_vao(name)
    ^^^^^^^^^^^^^^^^^^^
    File "C:\Users\infamoose\Documents\coding\spellsmithAgain\utility\shaderManager.py", line 61, in _get_vao
    vao = self.ctx.vertex_array(
    ^^^^^^^^^^^^^^^^^^^^^^
    File "C:\Users\infamoose\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.11_qbz5n2kfra8p0\LocalCache\local-packages\Python311\site-packages\moderngl\__init__.py", line 1901, in vertex_array
    return self._vertex_array(*args, **kwargs)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "C:\Users\infamoose\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.11_qbz5n2kfra8p0\LocalCache\local-packages\Python311\site-packages\moderngl\__init__.py", line 1922, in _vertex_array
    res.mglo, res._glo = self.mglo.vertex_array(
    ^^^^^^^^^^^^^^^^^^^^^^^
    _moderngl.Error: cannot create vertex array

    Continue reading...

Compartilhe esta Página