在pyopengl中无限渲染透明图像
Posted
技术标签:
【中文标题】在pyopengl中无限渲染透明图像【英文标题】:Transparent image rendering infinitely in pyopengl 【发布时间】:2021-12-05 06:49:35 【问题描述】:我已从这篇帖子 here 中获取代码。我的主要目标是在 OpenGL 中绘制我的整个 PyGame 项目,以便它能够更好地运行。我遇到的问题是我有一个有点透明的图像,看起来它被无限绘制并且失去了颜色和不透明度。我也尝试过其他不透明的图像,它似乎在做同样的事情。
Link for the transparent image I am using.
代码:
import pygame
from OpenGL.GL import *
from pygame.locals import *
pygame.init()
pygame.display.set_mode((1900, 900), OPENGL | DOUBLEBUF | pygame.OPENGLBLIT)
pygame.display.init()
info = pygame.display.Info()
# basic opengl configuration
glViewport(0, 0, info.current_w, info.current_h)
glDepthRange(0, 1)
glMatrixMode(GL_PROJECTION)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
glShadeModel(GL_SMOOTH)
glClearColor(0.0, 0.0, 0.0, 0.0)
glClearDepth(1.0)
glDisable(GL_DEPTH_TEST)
glDisable(GL_LIGHTING)
glDepthFunc(GL_LEQUAL)
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)
glEnable(GL_BLEND)
# Images
sun = pygame.image.load("menuimages/sun.png").convert_alpha()
texID = glGenTextures(1)
def surfaceToTexture( pygame_surface ):
global texID
rgb_surface = pygame.image.tostring(pygame_surface, 'RGB')
glBindTexture(GL_TEXTURE_2D, texID)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP)
surface_rect = pygame_surface.get_rect()
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, surface_rect.width, surface_rect.height, 0, GL_RGB, GL_UNSIGNED_BYTE, rgb_surface)
glGenerateMipmap(GL_TEXTURE_2D)
glBindTexture(GL_TEXTURE_2D, 0)
clock = pygame.time.Clock()
# make an offscreen surface for drawing PyGame to
offscreen_surface = pygame.Surface((info.current_w, info.current_h))
while True:
offscreen_surface.blit(sun, (50, 250))
# prepare to render the texture-mapped rectangle
glClear(GL_COLOR_BUFFER_BIT)
glLoadIdentity()
glDisable(GL_LIGHTING)
glEnable(GL_TEXTURE_2D)
#draw texture openGL Texture
surfaceToTexture( offscreen_surface )
glBindTexture(GL_TEXTURE_2D, texID)
glBegin(GL_QUADS)
glTexCoord2f(0, 0); glVertex2f(-1, 1)
glTexCoord2f(0, 1); glVertex2f(-1, -1)
glTexCoord2f(1, 1); glVertex2f(1, -1)
glTexCoord2f(1, 0); glVertex2f(1, 1)
glEnd()
pygame.display.flip()
clock.tick(60)
感谢任何帮助。
【问题讨论】:
【参考方案1】:IT 没有必要在应用程序循环中调用surfaceToTexture
。在循环之前调用一次,但在循环中绑定纹理。
此外,您还必须处理应用程序循环中的事件。分别见pygame.event.get()
pygame.event.pump()
:
对于游戏的每一帧,您都需要对事件队列进行某种调用。这确保您的程序可以在内部与操作系统的其余部分进行交互。
offscreen_surface.blit(sun, (50, 250))
surfaceToTexture( offscreen_surface )
run = True
while run:
for event in pygame.event.get():
if event.type == QUIT:
run = False
# prepare to render the texture-mapped rectangle
glClear(GL_COLOR_BUFFER_BIT)
glLoadIdentity()
glDisable(GL_LIGHTING)
glEnable(GL_TEXTURE_2D)
#draw texture openGL Texture
glBindTexture(GL_TEXTURE_2D, texID)
glBegin(GL_QUADS)
glTexCoord2f(0, 0); glVertex2f(-1, 1)
glTexCoord2f(0, 1); glVertex2f(-1, -1)
glTexCoord2f(1, 1); glVertex2f(1, -1)
glTexCoord2f(1, 0); glVertex2f(1, 1)
glEnd()
pygame.display.flip()
clock.tick(60)
现有的纹理对象 (texID
) 可以使用 glTexSubImage2D
进行更改:
def updateTexture(pygame_surface, texID):
rgb_surface = pygame.image.tostring(pygame_surface, 'RGB')
surface_rect = pygame_surface.get_rect()
glBindTexture(GL_TEXTURE_2D, texID)
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, surface_rect.width, surface_rect.height, GL_RGB, GL_UNSIGNED_BYTE, rgb_surface)
当您想要移动时,您应该更喜欢仅绘制和移动“小”图像。用glOrtho
设置Orthographic projection 并用窗口坐标指定四边形顶点。
另请参阅Render pygame sprites with pyopengl 或 PyGame and OpenGL immediate mode (Legacy OpenGL)
完整示例:
import pygame
from OpenGL.GL import *
from pygame.locals import *
pygame.init()
screen = pygame.display.set_mode((1900, 900), OPENGL | DOUBLEBUF | pygame.OPENGLBLIT)
pygame.display.init()
info = pygame.display.Info()
# basic opengl configuration
glViewport(0, 0, info.current_w, info.current_h)
glDepthRange(0, 1)
glMatrixMode(GL_PROJECTION)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
glShadeModel(GL_SMOOTH)
glClearColor(0.0, 0.0, 0.0, 0.0)
glClearDepth(1.0)
glDisable(GL_LIGHTING)
glDepthFunc(GL_LEQUAL)
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)
# Images
sun = pygame.image.load("menuimages/sun.png").convert_alpha()
def surfaceToTexture(pygame_surface):
texID = glGenTextures(1)
rgb_surface = pygame.image.tostring(pygame_surface, 'RGBA')
glBindTexture(GL_TEXTURE_2D, texID)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP)
surface_rect = pygame_surface.get_rect()
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, surface_rect.width, surface_rect.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, rgb_surface)
glGenerateMipmap(GL_TEXTURE_2D)
glBindTexture(GL_TEXTURE_2D, 0)
return texID
def drawTextureImage(textureId, rect):
glEnable(GL_TEXTURE_2D)
glBindTexture(GL_TEXTURE_2D, textureId)
glBegin(GL_QUADS)
glTexCoord2f(0, 0); glVertex2f(rect.left, rect.bottom)
glTexCoord2f(0, 1); glVertex2f(rect.left, rect.top)
glTexCoord2f(1, 1); glVertex2f(rect.right, rect.top)
glTexCoord2f(1, 0); glVertex2f(rect.right, rect.bottom)
glEnd()
glDisable(GL_TEXTURE_2D)
clock = pygame.time.Clock()
sun_x = 0
texID = surfaceToTexture(sun)
run = True
while run:
for event in pygame.event.get():
if event.type == QUIT:
run = False
sun_x = (sun_x + 1) % screen.get_width()
sun_rect = sun.get_rect(topleft = (sun_x, 250))
glViewport(0, 0, screen.get_width(), screen.get_height())
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glOrtho(0, screen.get_width(), 0, screen.get_height(), -1, 1)
glMatrixMode(GL_MODELVIEW)
# prepare to render the texture-mapped rectangle
glClear(GL_COLOR_BUFFER_BIT)
glLoadIdentity()
glDisable(GL_LIGHTING)
glDisable(GL_DEPTH_TEST)
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
#draw texture openGL Texture
drawTextureImage(texID, sun_rect)
pygame.display.flip()
clock.tick(60)
【讨论】:
以上是关于在pyopengl中无限渲染透明图像的主要内容,如果未能解决你的问题,请参考以下文章