如何在 PyOpenGL 中将 png 图像作为图像叠加层进行 blit?
How to blit a png image as an image overlay in PyOpenGL?
我正在 PyOpenGL 中制作游戏,并希望将一些图像作为叠加层(例如,暂停按钮)blit 到屏幕上。我该怎么做?
我试过使用 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>)```
glBitmap
, because the buffer is treated as a buffer with format GL_COLOR_INDEX
(see glTexImage2D
)
无法绘制格式为GL_RGBA8
的位图
参见 OpenGL 4.6 API Compatibility Profile Specification - 14.8 Bitmaps,第 579 页:
Like a polygon pattern, a bitmap is unpacked from memory according to the
procedure given in section 18.1 for DrawPixels; it is as if the width and height
passed to that command were equal to w and h, respectively, the type were BITMAP,
and the format were COLOR_INDEX.
如果您想绘制 RGBA trexutre,则必须创建一个小山阵列缓冲区。这可以通过 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)
我正在 PyOpenGL 中制作游戏,并希望将一些图像作为叠加层(例如,暂停按钮)blit 到屏幕上。我该怎么做?
我试过使用 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>)```
glBitmap
, because the buffer is treated as a buffer with format GL_COLOR_INDEX
(see glTexImage2D
)
GL_RGBA8
的位图
参见 OpenGL 4.6 API Compatibility Profile Specification - 14.8 Bitmaps,第 579 页:
Like a polygon pattern, a bitmap is unpacked from memory according to the procedure given in section 18.1 for DrawPixels; it is as if the width and height passed to that command were equal to w and h, respectively, the type were BITMAP, and the format were COLOR_INDEX.
如果您想绘制 RGBA trexutre,则必须创建一个小山阵列缓冲区。这可以通过 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)