Pyopengl:使用 GLSL 填充屏幕创建立方体

Pyopengl: Creating cube with GLSL fills screen

当我尝试使用 OpenGL 的 GLSL 可编程管道绘制立方体时,我得到一个全黄色的屏幕,这是立方体的颜色,即使我使用 glTranslatef() 并尝试缩小任意值, 屏幕完全是黄色的。我如何缩小才能看到整个立方体,而不仅仅是纯黄色的屏幕?

完整的可复制代码:

import time
import pygame
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
from OpenGL.GL.shaders import *
import numpy

width = 500
height = 500
vertices = [(-1, -1, -1), (1, -1, -1), (1, 1, -1), (-1, 1, -1), (-1, -1, 1), (1, -1, 1), (1, 1, 1), (-1, 1, 1)]
faces = [(4, 0, 3, 7), (1, 0, 4, 5), (0, 1, 2, 3), (1, 5, 6, 2), (3, 2, 6, 7), (5, 4, 7, 6)]

def draw_shapes():
    cube = []

    for i, face in enumerate(faces):
        for vertex in face:
            cube.append(vertices[vertex])
    cube = numpy.array(cube, dtype=numpy.float32)
    vertex_shader = """
        #version 140
        in vec4 position;
        void main(){
            gl_Position = position;
            
        }
    """

    frag_shader = """
        #version 140
        void main(){
            gl_FragColor = vec4(1.0f, 1.0f, 0.0f, 1.0f);
        }
        
    """

    shaders = compileProgram(compileShader(vertex_shader, GL_VERTEX_SHADER),
                             compileShader(frag_shader, GL_FRAGMENT_SHADER))
    VBO = glGenBuffers(1)
    glBindBuffer(GL_ARRAY_BUFFER, VBO)
    glBufferData(GL_ARRAY_BUFFER, 192, cube, GL_STATIC_DRAW)
    position = glGetAttribLocation(shaders, "position")
    glVertexAttribPointer(position, 3, GL_FLOAT, GL_FALSE, 0, None)
    glEnableVertexAttribArray(position)

    glUseProgram(shaders)

def showScreen():
    global width, height
    glClearColor(0, 0, 0, 1)
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    glDrawArrays(GL_TRIANGLES, 0, 24)
    draw_shapes()

    glEnable(GL_DEPTH_TEST)
    glEnable(GL_LIGHTING)
    glEnable(GL_LIGHT0)
    glEnable(GL_COLOR_MATERIAL)
    glLightfv(GL_LIGHT0, GL_POSITION, (0, 0, 0, 1))  # point light from the left, top, front
    glLightfv(GL_LIGHT0, GL_AMBIENT, (1, 1, 1, 1))


    glutSwapBuffers()

def reshapeWindow(x, y):
    global width, height
    width = x
    height = y
    print(x, y)
    glutReshapeWindow(width, height)
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    gluPerspective(45, (width / height), 0.0001, 1000)
    glViewport(0, 0, width, height)
    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity()
    glTranslatef(0, 0, -5)
    glRotatef(3, 1, 0, 0)

glutInit()
glutInitDisplayMode(GLUT_RGBA)
glutInitWindowSize(500, 500)
wind = glutCreateWindow("OpenGL")
glutDisplayFunc(showScreen)
glutIdleFunc(showScreen)
glutReshapeFunc(reshapeWindow)
gluPerspective(45, (width / height), 0.0001, 100)

while True:   
    glutMainLoopEvent()
    glutPostRedisplay()
    time.sleep(0.01)

正如 user253751 和 derhass 在评论中指出的那样,该代码将固定流水线 OpenGL 方法与现代 OpengL 的可编程着色器阶段方法混合在一起,而它应该是其中之一。遗留功能目前没有效果。最好使用有关现代 OpenGL 的书籍或教程重新开始,而不是转换遗留项目。

该项目的现代 OpenGL 版本将涉及:

  • 在 CPU.
  • 上定义变换矩阵 (model/view/projection)
  • 正在将一个或多个变换矩阵作为制服上传到 GPU。
  • 将灯光参数作为制服上传到 GPU。
  • 使用顶点着色器将每个顶点与变换矩阵相乘。
  • 在顶点着色器(对于高氏着色)或片段着色器(对于Blinn-Phong/Phong 着色)中手动编程 lighting/shading 计算。