在Python中绘制OpenGL三角形

vs3odd8k  于 2022-11-23  发布在  Python
关注(0)|答案(1)|浏览(305)

下面是我目前的代码:
main.py -

from Application import Application

    if __name__ == '__main__':
        app = Application()
        app.run()

Triangle.py -

import contextlib
    import logging as log
    from OpenGL import GL as gl
    import ctypes
    import sys

    class Triangle:
        vertex_array_id = 0
        vertex_data = []
        program_id = 0
        shader_id = 0

        def __init__(self):
            print('Triangle.__init__(self)')
            self.create_vertex_buffer()
            self.load_shaders()

        def create_vertex_array_object(self):
            log.debug('create_vertex_array_object(self):')
            self.vertex_array_id = gl.glGenVertexArrays(1)
            try:
                gl.glBindVertexArray(self.vertex_array_id)
                yield
            finally:
                log.debug('~create_vertex_array_object(self):')
                gl.glDeleteVertexArrays(1, [self.vertex_array_id])


        def create_vertex_buffer(self):
            with self.create_vertex_array_object():
                # A triangle
                self.vertex_data = [-1, -1, 0,
                               1, -1, 0,
                               0, 1, 0]
                attr_id = 0  # No particular reason for 0,
                # but must match the layout location in the shader.

                log.debug('creating and binding the vertex buffer (VBO)')
                vertex_buffer = gl.glGenBuffers(1)
                try:
                    gl.glBindBuffer(gl.GL_ARRAY_BUFFER, vertex_buffer)

                    array_type = (gl.GLfloat * len(self.vertex_data))
                    gl.glBufferData(gl.GL_ARRAY_BUFFER,
                                    len(self.vertex_data) * ctypes.sizeof(ctypes.c_float),
                                    array_type(*self.vertex_data),
                                    gl.GL_STATIC_DRAW)

                    log.debug('setting the vertex attributes')
                    gl.glVertexAttribPointer(
                        attr_id,  # attribute 0.
                        3,  # components per vertex attribute
                        gl.GL_FLOAT,  # type
                        False,  # to be normalized?
                        0,  # stride
                        None  # array buffer offset
                    )
                    gl.glEnableVertexAttribArray(attr_id)  # use currently bound VAO
                    yield
                finally:
                    log.debug('cleaning up buffer')
                    # gl.glDisableVertexAttribArray(attr_id)
                    # gl.glDeleteBuffers(1, [vertex_buffer])

        def load_shaders(self):
            shaders = {
                gl.GL_VERTEX_SHADER: '''\
                    #version 330 core
                    layout(location = 0) in vec3 vertexPosition_modelspace;
                    void main(){
                      gl_Position.xyz = vertexPosition_modelspace;
                      gl_Position.w = 1.0;
                    }
                    ''',
                gl.GL_FRAGMENT_SHADER: '''\
                    #version 330 core
                    out vec3 color;
                    void main(){
                      color = vec3(1,0,0);
                    }
                    '''
            }
            log.debug('creating the shader program')
            self.program_id = gl.glCreateProgram()
            try:
                shader_ids = []
                for shader_type, shader_src in shaders.items():
                    self.shader_id = gl.glCreateShader(shader_type)
                    gl.glShaderSource(self.shader_id, shader_src)

                    log.debug(f'compiling the {shader_type} shader')
                    gl.glCompileShader(self.shader_id)

                    # check if compilation was successful
                    result = gl.glGetShaderiv(self.shader_id, gl.GL_COMPILE_STATUS)
                    info_log_len = gl.glGetShaderiv(self.shader_id, gl.GL_INFO_LOG_LENGTH)
                    if info_log_len:
                        logmsg = gl.glGetShaderInfoLog(self.shader_id)
                        log.error(logmsg)
                        sys.exit(10)

                    gl.glAttachShader(self.program_id, self.shader_id)
                    shader_ids.append(self.shader_id)

                log.debug('linking shader program')
                gl.glLinkProgram(self.program_id)

                # check if linking was successful
                result = gl.glGetProgramiv(self.program_id, gl.GL_LINK_STATUS)
                info_log_len = gl.glGetProgramiv(self.program_id, gl.GL_INFO_LOG_LENGTH)
                if info_log_len:
                    logmsg = gl.glGetProgramInfoLog(self.program_id)
                    log.error(logmsg)
                    sys.exit(11)

                log.debug('installing shader program into rendering state')
                gl.glUseProgram(self.program_id)
                yield
            finally:
                log.debug('cleaning up shader program')
                for self.shader_id in self.shader_ids:
                    gl.glDetachShader(self.program_id, self.shader_id)
                    gl.glDeleteShader(self.shader_id)
                gl.glUseProgram(0)
                gl.glDeleteProgram(self.program_id)

        def render(self):
            gl.glDrawArrays(gl.GL_TRIANGLES, 0, 3)  # Starting from vertex 0

Application.py -

import contextlib
    import glfw
    import sys
    from OpenGL import GL as gl
    import logging as log

    from Triangle import Triangle

    class Application:

        tri = Triangle()

        def __init__(self):
            print("Application.__init__(self)")

        @contextlib.contextmanager
        def create_main_window(self):
            log.debug('create_main_window(self):')
            if not glfw.init():
                sys.exit(1)
            try:
                glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 3)
                glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 3)
                glfw.window_hint(glfw.OPENGL_FORWARD_COMPAT, True)
                glfw.window_hint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE)
                title = 'Tutorial 2: First Triangle'
                window = glfw.create_window(500, 400, title, None, None)
                if not window:
                    sys.exit(2)
                glfw.make_context_current(window)
                gl.glClearColor(0, 0, 0.4, 0)
                yield window

            finally:
                log.debug('~create_main_window(self):')
                glfw.terminate()

        def main_loop(self, window):
            while (
                    glfw.get_key(window, glfw.KEY_ESCAPE) != glfw.PRESS and
                    not glfw.window_should_close(window)
            ):
                gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)
                self.tri.render()
                glfw.swap_buffers(window)
                glfw.poll_events()

        def run(self):
            log.basicConfig(level=log.DEBUG)
            with self.create_main_window() as window:
                self.main_loop(window)

从控制台上,我看到了以下内容:

DEBUG:root:create_main_window(self):
Triangle.__init__(self)
Application.__init__(self)
DEBUG:root:~create_main_window(self):
Traceback (most recent call last):
   File "C:\Users\prussos\PycharmProjects\pythonProject3\main.py", line 5, in <module>
   app.run()
   File "C:\Users\prussos\PycharmProjects\pythonProject3\Application.py", line 51, in run
   self.main_loop(window)
   File "C:\Users\prussos\PycharmProjects\pythonProject3\Application.py", line 44, in main_loop
   self.tri.render()
   File "C:\Users\prussos\PycharmProjects\pythonProject3\Triangle.py", line 131, in render
   gl.glDrawArrays(gl.GL_TRIANGLES, 0, 3)  # Starting from vertex 0
   File "C:\Users\prussos\PycharmProjects\pythonProject3\venv\lib\site-packages\OpenGL\platform\baseplatform.py", line 415, in __call__
   return self( *args, **named )
   File "C:\Users\prussos\PycharmProjects\pythonProject3\venv\lib\site-packages\OpenGL\error.py", line 230, in glCheckError
   raise self._errorClass(
OpenGL.error.GLError: GLError(
   err = 1282,
   description = b'invalid operation',
   baseOperation = glDrawArrays,
   cArguments = (GL_TRIANGLES, 0, 3)
)

Process finished with exit code 1

似乎有一个绘图错误正在发生,但我真的不太清楚如何开始解决这个问题。代码从gitlabs转移到一个基于类的系统为python。所以,一个绘制数组,这是一个无效的操作什么可能是来自OpenGL库的人足够熟悉它知道什么地方编辑这里?

cygmwpex

cygmwpex1#

调用OpenGL指令时,需要一个有效的最新OpenGL上下文。OpenGL上下文是用OpenGl窗口创建的。OpenGL对象( VAO 、VBO和着色器)是在Triangle类的构造函数中创建的。因此,只有在创建OpenGL窗口后,才能构造此类的对象:

class Application:

    # tri = Triangle()              # <-- DELETE

    def __init__(self):
        print("Application.__init__(self)")

    @contextlib.contextmanager
    def create_main_window(self):
        log.debug('create_main_window(self):')
        if not glfw.init():
            sys.exit(1)
        try:
            glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 3)
            glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 3)
            glfw.window_hint(glfw.OPENGL_FORWARD_COMPAT, True)
            glfw.window_hint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE)
            title = 'Tutorial 2: First Triangle'
            window = glfw.create_window(500, 400, title, None, None)
            if not window:
                sys.exit(2)
            glfw.make_context_current(window)
            gl.glClearColor(0, 0, 0.4, 0)
            yield window

        finally:
            log.debug('~create_main_window(self):')
            glfw.terminate()

    def main_loop(self, window):

        self.tri = Triangle()          # IINSERT

        while (
                glfw.get_key(window, glfw.KEY_ESCAPE) != glfw.PRESS and
                not glfw.window_should_close(window)
        ):
            gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)
            self.tri.render()
            glfw.swap_buffers(window)
            glfw.poll_events()

    def run(self):
        log.basicConfig(level=log.DEBUG)
        with self.create_main_window() as window:
            self.main_loop(window)

相关问题