PyOpenGL渲染图片出现无限绘制、颜色与透明度丢失问题求助
问题根因
- 未逐帧清空PyGame离屏绘制表面,上一帧绘制的图案会残留在表面上,多次叠加后就会出现你观察到的无限叠加重绘的现象
- 透明度逻辑全链路缺失:
- 离屏表面创建时未开启alpha通道支持,无法存储半透明信息
- PyGame表面转OpenGL纹理时,仅提取了RGB三色数据,直接丢弃了图片自带的alpha通道值
- OpenGL开启了混合功能,但未配置正确的混合函数,半透明渲染规则不生效
修复方案
你需要对代码做以下几处修改:
- 创建离屏表面时添加
pygame.SRCALPHA参数,开启表面的alpha通道支持 - 初始化OpenGL配置时添加
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA),设置正确的半透明混合规则 - 修改
surfaceToTexture函数,用RGBA格式提取表面数据,OpenGL纹理也改为RGBA格式存储 - 每帧绘制前先填充清空离屏表面,清除上一帧的残留内容
修正后的完整代码如下:
import pygame from OpenGL.GL import * from pygame.locals import * pygame.init() pygame.display.set_mode((1900, 900), OPENGL | DOUBLEBUF | pygame.OPENGLBLIT) 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) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) # Images sun = pygame.image.load("menuimages/sun.png").convert_alpha() texID = glGenTextures(1) def surfaceToTexture( pygame_surface ): global texID # 改为提取RGBA格式数据 rgba_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() # 纹理改为RGBA格式存储 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, surface_rect.width, surface_rect.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, rgba_surface) glGenerateMipmap(GL_TEXTURE_2D) glBindTexture(GL_TEXTURE_2D, 0) clock = pygame.time.Clock() # 创建离屏表面时开启alpha通道支持 offscreen_surface = pygame.Surface((info.current_w, info.current_h), pygame.SRCALPHA) while True: # 每帧先清空离屏表面 offscreen_surface.fill((0,0,0,0)) 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)
内容的提问来源于stack exchange,提问作者ahmedquran12
相关产品推荐
相关产品推荐

