【问题标题】:Rendering Image in Pygame Using PyOpenGL使用 PyOpenGL 在 Pygame 中渲染图像
【发布时间】:2019-10-01 00:09:42
【问题描述】:

我正在为学校的计算机科学俱乐部开展一个项目,并尝试同时学习 Pygame/PyOpenGL。

现在我只是想做一些基本的事情。我正在尝试使用 Pygame 和 PyOpenGL 在窗口中渲染图像。这是我的代码的link(我不确定 Github 存储库是否正常)。

按要求编写代码(在 github 上更容易阅读):

import pygame
from OpenGL.GL import *
from OpenGL.GL import shaders
import unittest
import numpy as np
from ctypes import sizeof, c_float, c_void_p


def renderSplash(image):
       # using resources in open gl generally follows the form of generate, bind, modify

    # Generate: request a buffer for our vertices
    vbo = glGenBuffers(1)

    # Bind: set the newly requested buffer as the active GL_ARRAY_BUFFER. 
    #   All subsequent modifications of GL_ARRAY_BUFFER will affect our vbo
    glBindBuffer(GL_ARRAY_BUFFER, vbo)

    # Modify: Tell OpenGL to load data into the buffer. 

    # I've added two more coordinates to each vertex here for determining the position within the texture.
    # These two additional coordinates are typically refered to as uv coordinates.
    # Also there are now two triangles that cover the entire viewport.
    vertex_data = np.array([-1, -1, 0, 0,  -1, 1, 0, 1,  1, 1, 1, 1,  -1, -1, 0, 0,  1, 1, 1, 1,  1, -1, 1, 0], np.float32)
    glBufferData(GL_ARRAY_BUFFER, vertex_data, GL_STATIC_DRAW)

    vertex_position_attribute_location = 0
    uv_attribute_location = 1

    # glVertexAttribPointer basically works in the same way as glVertexPointer with two exceptions:
    #   First, it can be used to set the data source for any vertex attributes.
    #   Second, it has an option to normalize the data, which I have set to GL_FALSE.
    glVertexAttribPointer(vertex_position_attribute_location, 2, GL_FLOAT, GL_FALSE, sizeof(c_float)*4, c_void_p(0))
    # vertex attributes need to be enabled
    glEnableVertexAttribArray(0)
    glVertexAttribPointer(uv_attribute_location, 2, GL_FLOAT, GL_FALSE, sizeof(c_float)*4, c_void_p(sizeof(c_float)*2))
    glEnableVertexAttribArray(1)

    # Generate: request a texture
    image_texture = glGenTextures(1)

    # Bind: set the newly requested texture as the active GL_TEXTURE_2D.
    #   All subsequent modifications of GL_TEXTURE_2D will affect our texture (or how it is used)
    glBindTexture(GL_TEXTURE_2D, image_texture)


    width = image.get_width()
    height = image.get_height()

    # retrieve a byte string representation of the image.
    # The 3rd parameter tells pygame to return a vertically flipped image, as the coordinate system used
    # by pygame differs from that used by OpenGL
    image_data = pygame.image.tostring(image, "RGBA", True)

    # Modify: Tell OpenGL to load data into the image
    mip_map_level = 0
    glTexImage2D(GL_TEXTURE_2D, mip_map_level, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data)

    # set the filtering mode for the texture
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)

    vertex_shader = shaders.compileShader("""
        #version 330
        layout(location = 0) in vec2 pos;
        layout(location = 1) in vec2 uvIn;
        out vec2 uv;
        void main() {
            gl_Position = vec4(pos, 0, 1);
            uv = uvIn;
        }
        """, GL_VERTEX_SHADER)

    fragment_shader = shaders.compileShader("""
        #version 330
        out vec4 fragColor;
        in vec2 uv;
        uniform sampler2D tex;
        void main() {
            fragColor = texture(tex, uv);
        }
    """, GL_FRAGMENT_SHADER)

    shader_program = shaders.compileProgram(vertex_shader, fragment_shader)


    glEnableClientState(GL_VERTEX_ARRAY)

    # Enable alpha blending
    glEnable(GL_BLEND)
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

    glUseProgram(shader_program)

    glDrawArrays(GL_TRIANGLES, 0, 6)

def main():
    pygame.quit()
    pygame.init()
    image = pygame.image.load("Background.jpg")

    width = image.get_width()
    height = image.get_height()
    # width = 1920
    # height = 1080
    size = (width,height)
    pygame.display.set_mode(size, pygame.OPENGL | pygame.DOUBLEBUF | pygame.HWSURFACE)
    glViewport(0, 0, width, height)


    renderSplash(image)
    pygame.display.flip()
    close_window()

def close_window():
    key_pressed = False
    while not key_pressed:
        for event in pygame.event.get():
            if event.type == pygame.KEYDOWN:
                key_pressed = True

main()

我的问题是当我在桌面(Win10 Pro、1903、OS Build 18362.86、Python 3.7.2)上运行 SplashScreen.py 时,我得到以下信息

按要求以文本格式输出:

                                                      pygame 1.9.6
Hello from the pygame community. https://www.pygame.org/contribute.html
Traceback (most recent call last):
  File "SplashScreen.py", line 122, in <module>
    main()
  File "SplashScreen.py", line 111, in main
    renderSplash(image)
  File "SplashScreen.py", line 95, in renderSplash
    glDrawArrays(GL_TRIANGLES, 0, 6)
  File "C:\Users\LukeJ\AppData\Roaming\Python\Python37\site-packages\OpenGL\platform\baseplatform.py", line 402, in __call__
    return self( *args, **named )
OSError: exception: access violation reading 0x0000000000000000

但是,如果我在笔记本电脑(Win10 Pro、1903、OS Build 18362.86、Python 3.7.2)上运行此代码,它可以正常工作。

我在我的代码中做错了吗?我需要做些什么来测试这个问题并希望在我的代码中修复它?

【问题讨论】:

  • 请添加您的相关代码并作为文本提出问题。图片和链接没那么有用。
  • @KlausD。更新

标签: python opengl pygame pyopengl


【解决方案1】:

删除

glEnableClientState(GL_VERTEX_ARRAY)

你的代码就可以工作了。

glEnableClientState(GL_VERTEX_ARRAY) 启用顶点坐标的客户端功能,它激活了已弃用的固定函数属性,并且与Legacy OpenGL 相关。
这与顶点属性规范和glEnableVertexAttribArray(0) 相抵消。
固定函数顶点坐标必须由glVertexPointer 而不是glVertexAttribPointer 定义。 出现“读取0x0000000000000000的访问冲突”,因为没有固定函数函数顶点数据集,但是启用了。

【讨论】:

  • 成功了!那么,如果它们运行相同的操作系统,为什么这会在我的笔记本电脑上运行,而不是在我的台式机上运行呢?某种驱动差异?我的笔记本电脑运行的是 Intel HD,而我的台式机有一个专用的 GPU。也许就是这样?
  • @LukeKelly 这取决于图形硬件和 OpenGL 驱动程序。这可能与What are the Attribute locations for fixed function pipeline in OpenGL 4.0++ core profile?有关。
猜你喜欢
  • 2019-06-29
  • 2021-12-05
  • 2017-03-26
  • 1970-01-01
  • 2012-07-08
  • 2019-06-26
  • 2014-07-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多