PyGame窗口中OpenGL绘制的三角形无法显示问题排查
OpenGL + PyGame 绘制三角形不显示的问题排查
问题描述
使用PyGame创建窗口、OpenGL渲染三角形,代码已实现VAO/VBO绑定、着色器加载,但窗口始终无法显示白色三角形。顶点数据包含3个顶点(每个顶点含3个坐标+3个颜色值),窗口背景设为红色。
原代码实现
from OpenGL.GL import * import pygame as pg from pygame.locals import * import numpy as np import ctypes from OpenGL.GL.shaders import compileProgram,compileShader class Shape: def __init__(self,vertices:tuple,counter:int): self.shapeid:int = len(vertices)/6 self.vertices = np.array(vertices,dtype=np.float32) self.vao = glGenVertexArrays(counter) glBindVertexArray(self.vao) self.vbo = glGenBuffers(counter) glBindBuffer(GL_ARRAY_BUFFER,self.vbo) glBufferData(GL_ARRAY_BUFFER,self.vertices.nbytes,self.vertices,GL_STATIC_DRAW) glEnableVertexAttribArray(0) glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,24,ctypes.c_void_p(0)) glEnableVertexAttribArray(1) glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE,24,ctypes.c_void_p(12)) class Window: shapes:list[Shape] = [] def __init__(self,width:int,height:int): display = (width,height) pg.display.set_mode(display,DOUBLEBUF|OPENGL) glClearColor(1.0,0.0,0.0,1) self.shader = self.createShader("Shaders/vertex.txt","Shaders/fragment.txt") glUseProgram(self.shader) def loop(self): while True: for event in pg.event.get(): if event.type==pg.QUIT: pg.quit() quit() glUseProgram(self.shader) for i in self.shapes: glBindVertexArray(i.vao) glDrawArrays(GL_LINES,0,3) def createShader(self,vertexShederFileName:str,fragmentShederFileName:str): with open(vertexShederFileName,'r') as v: vertex_src = v.readlines() with open(fragmentShederFileName,'r') as f: fragment_src = f.readlines() shader = compileProgram(compileShader(vertex_src,GL_VERTEX_SHADER),compileShader(fragment_src,GL_FRAGMENT_SHADER)) return shader def addShape(self,shape:Shape): self.shapes = self.shapes + [shape] pg.init() win = Window(720,360) triangle = (0.0,0.0,0.0,1.0,1.0,1.0, 1.0,0.0,0.0,1.0,1.0,1.0, 0.0,1.0,0.0,1.0,1.0,1.0 ) shape2 = Shape(triangle,1) win.addShape(shape2) win.loop()
错误点分析及修正方案
- 绘制模式错误:原代码用
GL_LINES模式,该模式会把3个顶点渲染成3条独立线段,无法形成填充三角形。需改为GL_TRIANGLES模式,才能正确渲染填充的三角形。 - 缺少帧缓冲区操作:渲染循环中未执行
glClear(GL_COLOR_BUFFER_BIT)清除上一帧缓冲区,也没调用pg.display.flip()交换双缓冲区,导致画面无法刷新显示。 - 视口未显式设置:虽PyGame创建窗口后会自动设置视口,但显式调用
glViewport(0, 0, width, height)能确保视口与窗口尺寸完全匹配,避免环境差异引发的渲染异常。 - 整数除法不规范:
Shape类中self.shapeid = len(vertices)/6用浮点数除法,改为//6做整数除法更符合顶点数为整数的逻辑。
修正后核心代码片段
Window类初始化新增视口设置
def __init__(self,width:int,height:int): display = (width,height) pg.display.set_mode(display,DOUBLEBUF|OPENGL) glViewport(0, 0, width, height) # 新增:显式设置视口 glClearColor(1.0,0.0,0.0,1) self.shader = self.createShader("Shaders/vertex.txt","Shaders/fragment.txt") glUseProgram(self.shader)
渲染循环修正
def loop(self): while True: for event in pg.event.get(): if event.type==pg.QUIT: pg.quit() quit() glClear(GL_COLOR_BUFFER_BIT) # 新增:清除颜色缓冲区 glUseProgram(self.shader) for i in self.shapes: glBindVertexArray(i.vao) glDrawArrays(GL_TRIANGLES,0,3) # 修正:绘制模式改为GL_TRIANGLES pg.display.flip() # 新增:交换双缓冲区
配套着色器示例
确保着色器与顶点属性对应,示例如下:
顶点着色器(vertex.txt)
#version 330 core layout (location = 0) in vec3 aPos; layout (location = 1) in vec3 aColor; out vec3 ourColor; void main() { gl_Position = vec4(aPos, 1.0); ourColor = aColor; }
片段着色器(fragment.txt)
#version 330 core out vec4 FragColor; in vec3 ourColor; void main() { FragColor = vec4(ourColor, 1.0); }
内容的提问来源于stack exchange,提问作者Root
相关产品推荐
相关产品推荐

