moderngl / moderngl-window

A cross platform utility library for ModernGL making window creation and resource loading simple
MIT License
244 stars 57 forks source link

Call native gl functions via PyOpenGL has no context #49

Closed Remering closed 4 years ago

Remering commented 4 years ago

Backend: glfw Context OpenGL version: 450 core Operation system: Windows 10 Python interpreter: Python 3.8.0 [MSC v.1916 64 bit (AMD64)] on win32

I want to call glPolygonMode via PyOpenGL, but a GLError is raised.

Code:

from moderngl-window import *
from moderngl import *
from PyOpenGL.GL import *
import ctypes
import logging

class Config(WindowConfig)
    # Useless details....
    def render(self, time: float, frame_time: float):
        try:
            glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)
        except GLError as error:
            logging.error(ctypes.cast(error.description, ctypes.c_char_p).value)
            raise error

run_window_config(Config)

Error log:

python main.py --window glfw
2019-11-16 03:26:36,106 - moderngl_window - INFO - Attempting to load window class: moderngl_window.context.glfw.Window
2019-11-16 03:26:36,487 - moderngl_window.context.base.window - INFO - Context Version:
2019-11-16 03:26:36,487 - moderngl_window.context.base.window - INFO - ModernGL: 5.5.4
2019-11-16 03:26:36,487 - moderngl_window.context.base.window - INFO - vendor: NVIDIA Corporation
2019-11-16 03:26:36,487 - moderngl_window.context.base.window - INFO - renderer: GeForce GTX 1050 Ti/PCIe/SSE2
2019-11-16 03:26:36,487 - moderngl_window.context.base.window - INFO - version: 4.5.0 NVIDIA 431.23
2019-11-16 03:26:36,487 - moderngl_window.context.base.window - INFO - python: 3.8.0 (tags/v3.8.0:fa919fd, Oct 14 2019, 19:37:50) [MSC v.1916 64 bit (AMD64)]
2019-11-16 03:26:36,488 - moderngl_window.context.base.window - INFO - platform: win32
2019-11-16 03:26:36,488 - moderngl_window.context.base.window - INFO - code: 450
ERROR:root:None
Traceback (most recent call last):
  File "main.py", line 142, in <module>
    run_window_config(Config)
  File "C:\Users\mafumafu\AppData\Local\Programs\Python\Python38\lib\site-packages\moderngl_window\__init__.py", line 198, in run_window_config
    window.render(current_time, delta)
  File "C:\Users\mafumafu\AppData\Local\Programs\Python\Python38\lib\site-packages\moderngl_window\context\base\window.py", line 588, in render
    self.render_func(time, frame_time)
  File "C:/WorkPlace/Python/glumpy_demo/main.py", line 127, in render
    raise error
  File "C:/WorkPlace/Python/glumpy_demo/main.py", line 124, in render
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)
  File "C:\Users\mafumafu\AppData\Local\Programs\Python\Python38\lib\site-packages\OpenGL\platform\baseplatform.py", line 402, in __call__
    return self( *args, **named )
  File "C:\Users\mafumafu\AppData\Local\Programs\Python\Python38\lib\site-packages\OpenGL\error.py", line 228, in glCheckError
    raise GLError(
OpenGL.error.GLError: GLError(
    err = 1280,
    description = b'\xce\xde\xd0\xa7\xc1\xd0\xbe\xd9',
    baseOperation = glPolygonMode,
    cArguments = (GL_FRONT_AND_BACK, GL_LINE)
)

It seems that the lack of a OpenGL context. I put a breakpoint at moderngl_window/context/glfw/__init__.py: line 61

61|    glfw.make_context_current(self._window)

after that line is executed, I could call native OpenGL functions via PyOpenGL image image But I'm confused why I can't do the same thing in render function, is there a solution? Thanks a lot.

einarf commented 4 years ago

This is probably just a lingering glError that happened during initialization. Consume that error with pyopengl or self.ctx.error in your __init__.

I should probably ensure in the window itself there are no errors lingering.

EDIT: Never mind. I'm already doing this

https://github.com/moderngl/moderngl-window/blob/3b503d25eaa9c3af0fa416c156c090d9884b1344/moderngl_window/context/base/window.py#L138-L140

einarf commented 4 years ago

Are you running it with run_window_config(Config) ? Also, does one of the examples even work for you in the examples directory?

einarf commented 4 years ago

This works for me. It does indeed look like a glerror was lingering from somewhere..

import moderngl_window
from OpenGL.GL import *

class BasicWindowConfig(moderngl_window.WindowConfig):
    """Minimal WindowConfig example"""
    gl_version = (3, 3)
    title = "Basic Window Config"

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        # Consume lingering glerror from somewhere
        self.ctx.error

    def render(self, time, frametime):
        glClearColor(1.0, 0.0, 0.0, 0.0)
        glClear(GL_COLOR_BUFFER_BIT)

if __name__ == '__main__':
    moderngl_window.run_window_config(BasicWindowConfig)
einarf commented 4 years ago

Yep. It's a lingering glError from querying the context info. Everything should work if you just consume the glerror. Meanwhile I'll fix this bug.

The err = 1280 you are getting is just a GL_INVALID_ENUM lingering from earlier. If you did not have a context you would see a completely different error.

einarf commented 4 years ago

Released a new version: 2.0.2 that should fix this.

Upgrade with pip install -U moderngl-window

Also added a basic pyopengl example: https://github.com/moderngl/moderngl-window/blob/master/examples/with_pyopengl.py

Please let me know if this resolves your issue.

Remering commented 4 years ago

Are you running it with run_window_config(Config) ? Also, does one of the examples even work for you in the examples directory?

I am running it with run_window_config(Config), I have added that. Some of the examples do work, but others haven't been tested.

einarf commented 4 years ago

Upgrade to moderngl-window 2.0.2 and I'm 99% sure your issues will be resolved!

Remering commented 4 years ago

This works for me. It does indeed look like a glerror was lingering from somewhere..

import moderngl_window
from OpenGL.GL import *

class BasicWindowConfig(moderngl_window.WindowConfig):
    """Minimal WindowConfig example"""
    gl_version = (3, 3)
    title = "Basic Window Config"

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        # Consume lingering glerror from somewhere
        self.ctx.error

    def render(self, time, frametime):
        glClearColor(1.0, 0.0, 0.0, 0.0)
        glClear(GL_COLOR_BUFFER_BIT)

if __name__ == '__main__':
    moderngl_window.run_window_config(BasicWindowConfig)

After I add self.ctx.error at the top __init__ function, everything goes pretty fine. Many thanks to you!

Remering commented 4 years ago

I'm cloning this project because my mirror doesn't contain the latest version.

einarf commented 4 years ago

ah ok. git pull then 😄

Good luck with your projects @Remering and do not hesitate to open new issues if you stumble over something weird.

Remering commented 4 years ago

Ok, the latest release has fixed the issue. Happy hacking!!