如何在 PyOpenGL 中将 png 图像作为图像叠加层?

Posted

技术标签:

【中文标题】如何在 PyOpenGL 中将 png 图像作为图像叠加层?【英文标题】:How to blit a png image as an image overlay in PyOpenGL? 【发布时间】:2019-06-26 07:24:29 【问题描述】:

我正在使用 PyOpenGL 制作游戏,并希望将一些图像作为一些叠加层(例如,暂停按钮)在屏幕上显示。我该怎么做?

我尝试过使用glBitmap(),但它不起作用。

这就是我所拥有的:

pauseimg = pygame.image.load(path + "pause.png").convert_alpha()
def blit_image(x,y,w,h,img,r,g,b):
    glColor3f(r,g,b)
    glWindowPos2f(x,y)
    glBitmap(w,h,0,0,0,0,img)
blit_image(300,300,313,115,pauseimg,1,1,1)

我希望它会 blit 图像,但它却抛出了异常:

Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/OpenGL/latebind.py", line 41, in __call__
    return self._finalCall( *args, **named )
TypeError: 'NoneType' object is not callable

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File ".py", line 438, in <module>
    blit_image(300,300,313,115,pauseimg,1,1,1)
  File ".py", line 135, in blit_image
    glBitmap(w,h,0,0,0,0,img)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/OpenGL/latebind.py", line 45, in __call__
    return self._finalCall( *args, **named )
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/OpenGL/wrapper.py", line 675, in wrapperCall
    pyArgs = tuple( calculate_pyArgs( args ))
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/OpenGL/wrapper.py", line 436, in calculate_pyArgs
    yield converter(args[index], self, args)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/OpenGL/converters.py", line 135, in __call__
    return self.function( incoming )
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/OpenGL/arrays/arraydatatype.py", line 149, in asArray
    return cls.getHandler(value).asArray( value, typeCode or cls.typeConstant )
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/OpenGL/arrays/arraydatatype.py", line 53, in __call__
    typ.__module__, type.__name__, repr(value)[:50]
TypeError: ('No array-type handler for type pygame.type (value: <Surface(313x114x32 SW)>) registered', <OpenGL.converters.CallFuncPyConverter object at 0x111a720b8>)```

【问题讨论】:

我发现我必须将图像加载为位图数组。怎么样? 尝试使用 glDrawPixels,但不知道如何。 【参考方案1】:

glBitmap 无法绘制格式为GL_RGBA8 的位图,因为缓冲区被视为格式为GL_COLOR_INDEX 的缓冲区(参见glTexImage2D

参见OpenGL 4.6 API Compatibility Profile Specification - 14.8 Bitmaps,第 579 页:

像多边形图案一样,位图是根据 第 18.1 节中给出的 DrawPixels 程序;好像宽度和高度 传递给该命令的分别等于 w 和 h,类型为 BITMAP, 格式为 COLOR_INDEX。


如果你想绘制一个 RGBA trexutre,那么你必须创建一个 butte 数组缓冲区。这可以通过NumPy实现:

raw_data = img.get_buffer().raw
data = numpy.fromstring(raw_data, numpy.uint8)

通过glTexImage2D创建纹理对象:

bitmap_tex = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D, bitmap_tex)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_BGRA,GL_UNSIGNED_BYTE,data)

并通过Quads - Primitive绘制纹理:

glEnable(GL_TEXTURE_2D)
glBegin(GL_QUADS)
glTexCoord2f(0, 1)
glVertex2f(x, y)
glTexCoord2f(1, 1)
glVertex2f(x+w, y)
glTexCoord2f(1, 0)
glVertex2f(x+w, y+h)
glTexCoord2f(0, 0)
glVertex2f(x, y+h)
glEnd()
glDisable(GL_TEXTURE_2D)

如果纹理是透明的,那么你必须激活Blending。 该功能可以实现如下:

bitmap_tex = None
def blit_image(x,y,img,r,g,b):
    global bitmap_tex

    # get texture data
    w,h = img.get_size()
    raw_data = img.get_buffer().raw
    data = numpy.fromstring(raw_data, numpy.uint8)

    # create texture object
    if bitmap_tex == None:
      bitmap_tex = glGenTextures(1)
    glBindTexture(GL_TEXTURE_2D, bitmap_tex)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
    glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_BGRA,GL_UNSIGNED_BYTE,data)

    # save and set model view and projection matrix
    glMatrixMode(GL_PROJECTION)
    glPushMatrix()
    glLoadIdentity()
    glOrtho(0, display[0], 0, display[1], -1, 1)
    glMatrixMode(GL_MODELVIEW)
    glPushMatrix()
    glLoadIdentity()

    # enable blending
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
    glEnable(GL_BLEND)

    # draw textured quad
    glColor3f(r,g,b)

    glEnable(GL_TEXTURE_2D)
    glBegin(GL_QUADS)
    glTexCoord2f(0, 1)
    glVertex2f(x, y)
    glTexCoord2f(1, 1)
    glVertex2f(x+w, y)
    glTexCoord2f(1, 0)
    glVertex2f(x+w, y+h)
    glTexCoord2f(0, 0)
    glVertex2f(x, y+h)
    glEnd()
    glDisable(GL_TEXTURE_2D)

    # restore matrices
    glMatrixMode(GL_PROJECTION)
    glPopMatrix()
    glMatrixMode(GL_MODELVIEW)
    glPopMatrix()

    # disable blending
    glDisable(GL_BLEND)
pauseimg = pygame.image.load(path + "pause.png").convert_alpha()
blit_image(300,300,pauseimg,1,1,1)

【讨论】:

原始数据是指png文件吗?如何加载它们? 那么如何在 PyOpenGL 中将 2d 图像作为叠加层? 为什么它什么都没有? 另外,glOrtho(0, window_width, 0, window_height, -1, 1) 也不起作用。它给了我一个空白的视图。 我想我试过了。我有gluPerspective()gluLookAt() 工作。有关系吗?

以上是关于如何在 PyOpenGL 中将 png 图像作为图像叠加层?的主要内容,如果未能解决你的问题,请参考以下文章

PyOpenGL - 如何加载在 mtl 文件中定义了颜色的 obj 文件

如何在R中将highchart保存为PNG图像?

在 PHP 中将 2 个或更多 png 图像合并到基本图像上

如何在 PHP 中将图像从 base 64 转换为它们的文件类型?

如何将 PYopenGL 写入 JPG 图像

如何在 react-native 中将 JPG 图像转换为 PNG