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 计算。
当我尝试使用 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 计算。