python - 使用 (py)OpenGL 处理纹理和图像

标签 python opengl pygame python-imaging-library pyopengl

我最近开始接触 pygame,并最终进入 pyOpenGL(仅使用二维),因为用 pygame 将图像绘制到屏幕上时有些卡顿。然而,我遇到了两个问题,我一生都不知道如何解决。即处理两个以上纹理并解决加载图像时 pygame 和 OpenGL 的坐标不兼容问题。

我创建了一个名为 Thingie1 的简单类:

class Thingie1:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.width = 0
        self.height = 0
        self.sprite = "imageOne.png"
        self.lastsprite = ""
        self.img_data = 0
        self.load()

    def load(self):
        if self.sprite != self.lastsprite:
            im = open(self.sprite)
            self.width, self.height, self.img_data = im.size[0], im.size[1], im.tobytes("raw", "RGB", 0, -1)
            self.lastsprite = self.sprite

            self.Texture = glGenTextures(1)
            glBindTexture(GL_TEXTURE_2D, self.Texture)
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, self.width, self.height, 0, GL_RGB, GL_UNSIGNED_BYTE, self.img_data)
            glEnable(GL_TEXTURE_2D)
        else:
            return

    def draw(self):
        glMatrixMode(GL_MODELVIEW)
        glLoadIdentity()
        glTranslate(self.x, self.y, 0)
        glBegin(GL_QUADS)
        glVertex(0, 0, 0)
        glTexCoord2f(0, 0)
        glVertex(self.width, 0, 0)
        glTexCoord2f(0, 1)
        glVertex(self.width, self.height, 0)
        glTexCoord2f(1, 1)
        glVertex(0, self.height, 0)
        glTexCoord2f(1, 0)
        glEnd()
        glFlush()

以及所提到的类的精确副本(目前),称为 Thingie2。 (open() 函数来自 PILLOW 的 Image 包(from PIL.Image import open)。)

然后我打电话

pygame.init()
pygame.display.set_mode((1024,768), pygame.DOUBLEBUF | pygame.OPENGL)

if True:
    glClearColor(*(0,0,0,255))
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    gluOrtho2D(0, 1024, 768, 0)
    Thing1 = Thingie1(200,200)
    Thing2 = Thingie2(0,0)

    while True:
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()

        Thing2.load()
        Thing1.load()

        Thing2.draw()
        Thing1.draw()
        pygame.display.flip()

Thing2 之上绘制 Thing1,部分有效;之前,当 load()draw() 函数合并为一个时,它可以正确地对对象进行纹理处理,但对我的计算机来说并不友好。现在,它使用 Thing2 的纹理对两个类实例进行纹理处理,这是第一个问题。

第二个问题是,绘制的图像旋转了180°。我尝试过使用 matplotlib、cv2 和其他包来加载图像,但最接近解决此问题的是当我使用 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, self.width, self.height, 0, GL_RGB, GL_UNSIGNED_BYTE, self.img_data[::-1]) (使用 PIL.Image 的 open()),但是绘制图像灰色+蓝色刻度(?)。

那么,首先,pyOpenGL 一般如何处理纹理?我希望这两个纹理都存储在各自的 self.Texture 中。问题是它们都绑定(bind)到 GL_TEXTURE_2D 吗?我将如何区分这两种纹理?

其次,有没有更好的方法来加载图像,或者有没有一种方法可以以某种方式格式化图像像素字节数组,以便可以轻松反转(这适用于 RGBA)还有图像)?

最佳答案

请注意,该图由 glBegin/glEnd 绘制序列和固定函数矩阵堆栈几十年来已被弃用。请参阅Fixed Function PipelineLegacy OpenGL 。 了解 Vertex SpecificationShader最先进的渲染方式。

<小时/>

Now, it textures both class instances with Thing2's texture, which is the first issue.

二维纹理由 glEnable(GL_TEXTURE_2D) 启用并且可以通过 glDisable(GL_TEXTURE_2D) 禁用。
如果启用纹理,则当 glBegin/glEnd 绘制几何图形时当前绑定(bind)的纹理。应用序列。

在绘制几何图形之前,您必须绑定(bind)正确的纹理:

def draw(self):

    # [...]

    glEnable(GL_TEXTURE_2D)
    glBindTexture(GL_TEXTURE_2D, self.Texture)
    glBegin()

    # [...]     

    glEnd()
    glDisable(GL_TEXTURE_2D)
<小时/>

The second issue is, that the drawn image is rotated by 180°

何时 glVertex被调用时,当前纹理坐标与顶点坐标相关联。纹理坐标由 glTexCoord2f 设置.

这意味着glTexCoord2f必须在之前 glVertex 完成.

glBegin(GL_QUADS)

glTexCoord2f(0, 0)
glVertex(0, 0, 0)

glTexCoord2f(0, 1)
glVertex(self.width, 0, 0)

glTexCoord2f(1, 1)
glVertex(self.width, self.height, 0)

glTexCoord2f(1, 0)
glVertex(0, self.height, 0)

glEnd()

关于python - 使用 (py)OpenGL 处理纹理和图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54243031/

相关文章:

python - scrapy + adbapi = 属性错误 : 'module' object has no attribute 'DictCursor'

python - tkinter 条目和从右到左的光标

python - 安装Python GTK

optimization - 如何使用 SFML 更快地渲染 400 多个多边形

java - 我没有告诉它 VBO 渲染顶点

python - 如何让一个物体拥有暂时的无敌?

python - 使用 Python 和 boto3 通过 AWS SES 发送格式化的 html 电子邮件

opengl - 数百万个原语的哪种鼠标采摘策略?

python - 在Python中清除一个组

python - Pygame 中自上而下的运动/等距运动