我正在尝试在 Python 中使用 OpenGL。我还没有设法让深度测试发挥作用。 我还没有成功安装 GLUT,所以我只是使用 Pygame 创建窗口并且它可以工作。
仅激活深度测试 (
glEnable(GL_DEPTH_TEST)
) 会导致空白屏幕。
编写片段着色器来显示每个像素的深度值会导致所有对象都是纯白色(无论我距离它们有多近),而不是灰度,并且背景按预期为黑色。
#version 330 core
out vec4 fragColor;
void main()
{
fragColor = vec4(vec3(gl_FragCoord.z), 1.0);
}
我在某处读到,你需要在显示模式下请求深度缓冲区(使用 GLUT 时),但我还没有找到在 Pygame 中做到这一点的方法。
这是我的代码的最小版本:
import OpenGL
from OpenGL.GL import *
from OpenGL.GLU import *
import pygame
from pygame.locals import *
display = (2560, 1440)
def setup_perspective_projection():
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(70, (display[0] / display[1]), 0.0, 10.0)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
def draw_3d_cube(translatef_x, translatef_y, translatef_z):
setup_perspective_projection()
glTranslatef(translatef_x, translatef_y, translatef_z)
glBegin(GL_QUADS)
# Front face
glColor3f(1.0, 0.0, 0.0) # Red
glVertex3f(-1.0, -1.0, 1.0)
glVertex3f(1.0, -1.0, 1.0)
glVertex3f(1.0, 1.0, 1.0)
glVertex3f(-1.0, 1.0, 1.0)
# Back face
glColor3f(0.0, 1.0, 0.0) # Green
glVertex3f(-1.0, -1.0, -1.0)
glVertex3f(-1.0, 1.0, -1.0)
glVertex3f(1.0, 1.0, -1.0)
glVertex3f(1.0, -1.0, -1.0)
# Top face
glColor3f(0.0, 0.0, 1.0) # Blue
glVertex3f(-1.0, 1.0, -1.0)
glVertex3f(-1.0, 1.0, 1.0)
glVertex3f(1.0, 1.0, 1.0)
glVertex3f(1.0, 1.0, -1.0)
# Bottom face
glColor3f(1.0, 1.0, 0.0) # Yellow
glVertex3f(-1.0, -1.0, -1.0)
glVertex3f(1.0, -1.0, -1.0)
glVertex3f(1.0, -1.0, 1.0)
glVertex3f(-1.0, -1.0, 1.0)
# Right face
glColor3f(1.0, 0.0, 1.0) # Magenta
glVertex3f(1.0, -1.0, -1.0)
glVertex3f(1.0, 1.0, -1.0)
glVertex3f(1.0, 1.0, 1.0)
glVertex3f(1.0, -1.0, 1.0)
# Left face
glColor3f(0.0, 1.0, 1.0) # Cyan
glVertex3f(-1.0, -1.0, -1.0)
glVertex3f(-1.0, -1.0, 1.0)
glVertex3f(-1.0, 1.0, 1.0)
glVertex3f(-1.0, 1.0, -1.0)
glEnd()
# Shader source code
fragment_shader_source = """
#version 330 core
out vec4 fragColor;
void main()
{
fragColor = vec4(vec3(gl_FragCoord.z), 1.0);
}
"""
def compile_shader(shader_type, source):
shader = glCreateShader(shader_type)
glShaderSource(shader, source)
glCompileShader(shader)
return shader
def create_shader_program(fragment_source):
fragment_shader = compile_shader(GL_FRAGMENT_SHADER, fragment_source)
shader_program = glCreateProgram()
glAttachShader(shader_program, fragment_shader)
glLinkProgram(shader_program)
return shader_program
def main():
pygame.init()
pygame.display.set_mode(display, DOUBLEBUF | OPENGL | HWSURFACE | FULLSCREEN)
#glEnable(GL_DEPTH_TEST)
glDepthFunc(GL_LESS)
glEnable(GL_CULL_FACE)
shader_program = create_shader_program(fragment_shader_source)
glUseProgram(shader_program)
clock = pygame.time.Clock()
FPS = 144
while True:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
return
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
draw_3d_cube(-2, -2, -5)
draw_3d_cube(-2,-2,-10)
pygame.display.flip()
if __name__ == "__main__":
main()
您可能想在第 7 行更改显示器的分辨率/尺寸。 第 89 行是注释,因为否则屏幕是空白的。 要停用着色器,您只需删除第 94 行即可(您可以看到后面的立方体是如何绘制在前面的立方体前面的)。
gluPerspective
gluPerspective(70, (display[0] / display[1]), 0, 10.0)
gluPerspective(70, (display[0] / display[1]), 0.01, 10.0)
透视投影矩阵定义了一个视锥体,其中0< near < far。视锥体受到近平面和远平面的限制。几何体在截锥体的 6 个平面处被剪裁。近期计划的值为 0 会导致未定义的行为,并且很可能在内部计算中除以 0。