python - 使用 (py)OpenGL 处理纹理和图像
问题描述
我最近开始进入 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()
绘制Thing1
在 之上Thing2
,这部分工作;以前,当load()
anddraw()
函数合并为一个时,它可以正确地对对象进行纹理化,但对我的计算机并不完全友好。现在,它使用 Thing2 的纹理对两个类实例进行纹理处理,这是第一个问题。
第二个问题是,绘制的图像旋转了 180°。我已经尝试使用 matplotlib、cv2 和其他包来加载图像,但我最接近解决这个问题的是当我glTexImage2D
用glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, self.width, self.height, 0, GL_RGB, GL_UNSIGNED_BYTE, self.img_data[::-1])
(使用 PIL.Image's open()
)修改该行时,但这会以灰色+蓝色比例绘制图像(? )。
那么,首先,pyOpenGL 通常如何处理纹理?我希望这两种纹理都将存储在它们各自self.Texture
的 s. 他们俩都必然会遇到的问题GL_TEXTURE_2D
吗?我将如何区分这两种纹理?
其次,有没有更好的方法来加载图像,或者有没有办法以某种方式格式化图像像素字节数组,以便它可以轻松地反转(这也适用于 RGBA 图像)?
解决方案
请注意,由glBegin
/glEnd
序列绘制和固定函数矩阵堆栈自几十年以来已被弃用。请参阅固定功能管道和旧版 OpenGL。阅读有关顶点规范和着色器的信息,了解最先进的渲染方式。
现在,它使用 Thing2 的纹理对两个类实例进行纹理处理,这是第一个问题。
二维纹理由 启用glEnable(GL_TEXTURE_2D)
和禁用glDisable(GL_TEXTURE_2D)
。如果启用了纹理,则应用/序列
绘制几何图形时当前绑定的纹理。glBegin
glEnd
在绘制几何之前,您必须绑定正确的纹理:
def draw(self):
# [...]
glEnable(GL_TEXTURE_2D)
glBindTexture(GL_TEXTURE_2D, self.Texture)
glBegin()
# [...]
glEnd()
glDisable(GL_TEXTURE_2D)
第二个问题是,绘制的图像旋转了 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()
推荐阅读
- mysql - MYSQL 选择算术与列结果
- html - 如何获取网站上使用的所有字体系列的列表?
- c# - WCF Web 服务 DataContract 数组
- python - mousePressEvent 不适用于子小部件?
- java - Java 8:流的映射函数中的多个条件
- php - 如何在php中创建json数组
- php - 从 2018 年 9 月 28 日起实施最新的 Google Cloud Vision Api 文本/徽标识别更新 - LabelDetectionConfig?
- docker - k8s 上的 Dockerized Spring Boot 应用几乎占用了所有可用内存
- amazon-web-services - AWS - 限制特定域中的访问
- chef-infra - Artifactory、Chef 和 Chocolatey 如何协同工作?