You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 00:35:02