【问题标题】:OpenGL error related to context (PyOpenGL and pygame)与上下文相关的 OpenGL 错误(PyOpenGL 和 pygame)
【发布时间】:2022-10-01 15:05:46
【问题描述】:

我在尝试将参数传递给着色器时遇到了问题。

我的基类如下所示:

import pygame as pg
import sys
from core.input import Input

class Base(object):
    
    def __init__(self, screen_size=[512, 512]):
        
        pg.init()
        display_flags = pg.DOUBLEBUF | pg.OPENGL
        
        pg.display.gl_set_attribute(pg.GL_MULTISAMPLEBUFFERS, 1)
        pg.display.gl_set_attribute(pg.GL_MULTISAMPLESAMPLES, 4)
        pg.display.gl_set_attribute(
            pg.GL_CONTEXT_PROFILE_MASK,
            pg.GL_CONTEXT_PROFILE_CORE
        )
        self._Screen = pg.display.set_mode(screen_size, display_flags)
        
        # set caption on window
        pg.display.set_caption(\"Solar System Simulation\")
        
        self._Running = True
        self._Clock = pg.time.Clock()
        
        # for user input
        self._Input = Input()
        
    def initilize(self) -> None:
        pass
    
    def update(self) -> None:
        pass
    
    def run(self) -> None:
        
        # startup
        self.initilize()
        
        # main loop
        while self._Running:
            
            # handle input
            self._Input.update()
            if self._Input._Quit:
                self._Running = False
            
            # update
            self.update()
            
            # render
            pg.display.flip()
            
            # sync clock
            self._Clock.tick(60)
            
        # shutdown
        pg.quit()
        sys.exit()

使用它我可以成功运行以下测试代码:

from core.base import Base
from core.openGLUtils import OpenGLUtils
from OpenGL.GL import *

class Test(Base):
    
    def initilize(self) -> None:
        print(\"Init program...\")
        
        # vertex shader
        vert_code = \"\"\"
        void main()
        {
            gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
        }
        \"\"\"
        
        # fragment shader
        frag_code = \"\"\"
        out vec4 fragColor;
        void main()
        {
            fragColor = vec4(1.0, 1.0, 0.0, 1.0);
        }
        \"\"\"
        # print OpenGL info
        OpenGLUtils.printSystemInfo()
        
        # send code to GPU - compile - store - reference
        self.program_ref = OpenGLUtils.initializeProgram(vert_code, frag_code)
        
        # set vert arrat obj
        vao_ref = glGenVertexArrays(1)
        glBindVertexArray(vao_ref)
        
        # render settings (optional)
        glPointSize(10)

    def update(self) -> None:
        # select program for rendering
        glUseProgram(self.program_ref)
        
        # render geometric objects using selected programs
        glDrawArrays(GL_POINTS, 0, 1)

Test().run()

但是当我添加一个属性类时:

from OpenGL.GL import *
import numpy

class Attribute(object):
    
    def __init__(self, data_type, data):
        # type of element: int | float | vec2 | vec3 | vec4
        self._DataType = data_type

        # array of data to be stored in buffer
        self._Data = data
        
        # reference of available buffer from GPU
        self._BufferRef = glGenBuffers(1)
        
        # upload data immediately
        self.uploadData()
        
    def uploadData(self):
        # convert data to numpy array format
        #   convert numbers to 32 bit floats
        data = numpy.array(self._Data).astype(numpy.float32)
        
        # select buffer used by the following functions
        glBindBuffer(GL_ARRAY_BUFFER, self._BufferRef)
        glBufferData(GL_ARRAY_BUFFER, data.ravel(), GL_STATIC_DRAW)
        
    # associate variable in program with this bugger
    def associateVariable(self, program_ref, variable_name):
        # get reference for program variable with given name
        variable_ref = glGetAttribLocation(program_ref, variable_name)

        # if the program does not reference the variabel, then exit
        if variable_ref == -1:
            return
        
        # select buffer used by the following functions
        glBindBuffer(GL_ARRAY_BUFFER, self._BufferRef)
        
        # specify how data will be read from the currently bound buffer into the specified variable
        if self._DataType == \"int\":
            glVertexAttribPointer(variable_ref, 1, GL_INT, GL_FALSE, 0, None)
        elif self._DataType == \"float\":
            glVertexAttribPointer(variable_ref, 1, GL_FLOAT, GL_FALSE, 0, None)
        elif self._DataType == \"vec2\":
            glVertexAttribPointer(variable_ref, 2, GL_FLOAT, GL_FALSE, 0, None)
        elif self._DataType == \"vec3\":
            glVertexAttribPointer(variable_ref, 3, GL_FLOAT, GL_FALSE, 0, None)
        elif self._DataType == \"vec4\":
            glVertexAttribPointer(variable_ref, 4, GL_FLOAT, GL_FALSE, 0, None)
        else:
            raise Exception(f\"Attribute {variable_name} has unknown type {self._DataType}\")
        
        # indicate that data will be streamed to this variable
        glEnableVertexAttribArray(variable_ref)

并运行以下测试代码:

from core.base import Base
from core.openGLUtils import OpenGLUtils
from core.attribute import Attribute
from OpenGL.GL import *

class Test(Base):
    
    def initilize(self) -> None:
        print(\"Initializing program...\")
        
        # vert
        vs_code = \"\"\"
        in vec3 position;
        void main()
        {
            gl_Position = vec4(
                position.x, position.y, position.z, 1.0
            );
        }
        \"\"\"
        
        # frag
        fs_code = \"\"\"
        out vec4 fragColor;
        void main()
        {
            fragColor = vec4(1.0, 1.0, 0.0, 1.0);
        }
        \"\"\"
        
        self._ProgramRef = OpenGLUtils.initializeProgram(vs_code, fs_code)
        
        # render settings (optional)
        glLineWidth(4)
        
        # set up vertex array object
        vao_ref = glGenVertexArrays(1)
        glBindVertexArray(vao_ref)
        
        # set up vertex attribute
        position_data = [
            [0.8, 0.0, 0.0],    [0.4, 0.6, 0.0],
            [-0.4, 0.6, 0.0],   [-0.8, 0.0, 0.0],
            [-0.4, -0.6, 0.0],  [0.4, -0.6, 0.0]
        ]
        self._VertexCount = len(position_data)
        positionAttribute = Attribute(\"vec3\", position_data)
        positionAttribute.associateVariable(self._ProgramRef, \"position\")
        
        return super().initilize()
    
    def update(self) -> None:
        glUseProgram(self._ProgramRef)
        glDrawArrays(GL_LINE_LOOP, 0, self._VertexCount)
        
        return super().update()
    
Test().run()

导致以下错误消息:

pygame 2.1.2 (SDL 2.0.16, Python 3.8.14)
Hello from the pygame community. https://www.pygame.org/contribute.html
Initializing program...
Unable to load numpy_formathandler accelerator from OpenGL_accelerate
Traceback (most recent call last):
  File \"/home/jesper/dev/python3/solarpy/src/test2.py\", line 58, in <module>
    Test().run()
  File \"/home/jesper/dev/python3/solarpy/src/core/base.py\", line 38, in run
    self.initilize()
  File \"/home/jesper/dev/python3/solarpy/src/test2.py\", line 48, in initilize
    positionAttribute.associateVariable(self._ProgramRef, \"position\")
  File \"/home/jesper/dev/python3/solarpy/src/core/attribute.py\", line 48, in associateVariable
    glVertexAttribPointer(variable_ref, 3, GL_FLOAT, GL_FALSE, 0, None)
  File \"src/latebind.pyx\", line 51, in OpenGL_accelerate.latebind.Curry.__call__
  File \"/home/jesper/dev/python3/solarpy/lib/python3.8/site-packages/OpenGL/GL/VERSION/GL_2_0.py\", line 469, in glVertexAttribPointer
    contextdata.setValue( key, array )
  File \"/home/jesper/dev/python3/solarpy/lib/python3.8/site-packages/OpenGL/contextdata.py\", line 58, in setValue
    context = getContext( context )
  File \"/home/jesper/dev/python3/solarpy/lib/python3.8/site-packages/OpenGL/contextdata.py\", line 40, in getContext
    raise error.Error(
OpenGL.error.Error: Attempt to retrieve context when no valid context

我已经阅读了我在 StackOverflow 上找到的相关问题,但没有任何运气。我也尝试过使用不同的 python 版本(3.8、3.10)。

我在运行 Ubuntu 22.04.1 LTS(相对全新安装)的 Lenovo Thinkpad T460 上。

系统信息:

Vendor: Intel
Renderer: Mesa Intel(R) HD Graphics 520 (SKL GT2)
OpenGL version supported: 4.6 (Compatibility Profile) Mesa 22.0.5
GLSL version supported: 4.60

是什么导致了这个问题?据我了解,当使用pygame.OPENGL 标志集调用pygame.display.set_mode() 时,pygame 应该创建一个上下文,这是我在base.py 中完成的。

    标签: python python-3.x opengl pygame pyopengl


    【解决方案1】:

    当您调用 OpenGL API 函数时,您需要一个有效的 OpenGL 上下文。 OpenGL 上下文是使用 OpenGL 窗口创建的。因此,您必须先调用set_mode,然后才能使用OpenGL 指令。 set_modebase.initilize 中调用。因此super().initilize()必须在使用任何OpenGL API函数之前被调用:

    class Test(Base):
        
        def initilize(self) -> None:
            
            super().initilize()                       # <--- INSERT
    
            # [...]
    
            self._ProgramRef = OpenGLUtils.initializeProgram(vs_code, fs_code)
            
            # render settings (optional)
            glLineWidth(4)
            
            # set up vertex array object
            vao_ref = glGenVertexArrays(1)
            glBindVertexArray(vao_ref)
            
            # set up vertex attribute
            position_data = [
                [0.8, 0.0, 0.0],    [0.4, 0.6, 0.0],
                [-0.4, 0.6, 0.0],   [-0.8, 0.0, 0.0],
                [-0.4, -0.6, 0.0],  [0.4, -0.6, 0.0]
            ]
            self._VertexCount = len(position_data)
            positionAttribute = Attribute("vec3", position_data)
            positionAttribute.associateVariable(self._ProgramRef, "position")
            
            # return super().initilize()              # <--- DELETE
    

    【讨论】:

      猜你喜欢
      • 2019-06-14
      • 2021-04-30
      • 1970-01-01
      • 2023-03-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-12
      相关资源
      最近更新 更多