如何使用 pygame 和 pyopengl 正确添加灯光以使对象获得更好的视图
How to correctly add a light to make object get a better view with pygame and pyopengl
我正在学习 https://pythonprogramming.net/opengl-pyopengl-python-pygame-tutorial/ 中提供的教程,他在那里教授如何使用 pyOpenGL 渲染立方体 pygame。
渲染立方体时,教程为立方体的所有顶点设置颜色,然后显示。但是,在我的项目中,我使用 https://www.pygame.org/wiki/OBJFileLoader 中提供的代码从 .obj 文件加载对象,并且我的大部分对象都是完全白色的。
结论:当我在屏幕上渲染时,我只看到全白,非常难看。所以我想用光来更好地观察物体,但我做不到。
我对 pyOpenGl 知之甚少,找不到更深入的教程。
这里是教程中提供的部分代码和结果。 (顶点、边、表面和颜色变量是元组的元组)
def Cube():
glBegin(GL_QUADS)
for surface in surfaces:
x = 0
for vertex in surface:
x+=1
glColor3fv(colors[x])
glVertex3fv(verticies[vertex])
glEnd()
glBegin(GL_LINES)
for edge in edges:
for vertex in edge:
glVertex3fv(verticies[vertex])
glEnd()
def main():
pygame.init()
display = (800,600)
pygame.display.set_mode(display, DOUBLEBUF|OPENGL)
gluPerspective(45, (display[0]/display[1]), 0.1, 50.0)
glTranslatef(0.0,0.0, -5)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
glRotatef(1, 3, 1, 1)
Cube()
pygame.display.flip()
pygame.time.wait(10)
main()
我试图编辑主函数以插入一个简单的光,但立方体中的颜色刚刚消失:
def main():
pygame.init()
display = (800,600)
pygame.display.set_mode(display, DOUBLEBUF|OPENGL)
gluPerspective(45, (display[0]/display[1]), 0.1, 50.0)
glTranslatef(0.0,0.0, -5)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
glRotatef(1, 3, 1, 1)
glEnable(GL_LIGHTING)
glEnable(GL_LIGHT0)
glPushMatrix()
glTranslatef(0.0,0.0, 5)
glLight(GL_LIGHT0, GL_POSITION, (0, 1, 0, 1))
glLightfv(GL_LIGHT0, GL_AMBIENT, (0, 1.5, 1, 0))
glPopMatrix()
Cube()
glDisable(GL_LIGHT0)
glDisable(GL_LIGHTING)
pygame.display.flip()
pygame.time.wait(10)
我想要的是带有颜色并被灯光照亮的立方体。我的代码有什么问题以及如何修复它?
点亮时(GL_LIGHTING
) is enabled, then the color is taken from the material parameters (glMaterial
)。
如果您仍想使用当前颜色,则必须启用 GL_COLOR_MATERIAL
并设置颜色 material 参数 (glColorMaterial
).
环境光不依赖于光源的方向。您必须定义漫射 and/or 镜面光。见 glLightfv
:
当灯光位置由glLightfv(GL_LIGHT0, GL_POSITION, pos)
设置时,则该位置乘以当前模型视图矩阵。因此必须在模型转换之前设置 world space 中的光照位置。
在设置投影矩阵之前切换到矩阵模式GL_PROJECTION
。否则,光源位置将乘以投影矩阵。
glMatrixMode(GL_PROJECTION)
gluPerspective(45, (display[0]/display[1]), 0.1, 50.0)
glMatrixMode(GL_MODELVIEW)
glTranslatef(0, 0, -5)
#glLight(GL_LIGHT0, GL_POSITION, (0, 0, 1, 0)) # directional light from the front
glLight(GL_LIGHT0, GL_POSITION, (5, 5, 5, 1)) # point light from the left, top, front
glLightfv(GL_LIGHT0, GL_AMBIENT, (0, 0, 0, 1))
glLightfv(GL_LIGHT0, GL_DIFFUSE, (1, 1, 1, 1))
glEnable(GL_DEPTH_TEST)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
glEnable(GL_LIGHTING)
glEnable(GL_LIGHT0)
glEnable(GL_COLOR_MATERIAL)
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE )
glRotatef(1, 3, 1, 1)
Cube()
glDisable(GL_LIGHT0)
glDisable(GL_LIGHTING)
glDisable(GL_COLOR_MATERIAL)
pygame.display.flip()
漫射(和镜面反射)光取决于表面的 Normal 矢量。
定义一个法向量元组数组(x, y, z)
。注意下面的定义是一个例子。因为你画了一个有 6 个面的立方体,你必须定义 6 个法向量,但是向量的方向取决于你的顶点坐标,我不知道。
normals = [
( 0, 0, -1), # surface 0
(-1, 0, 0), # surface 1
( 0, 1, 1), # surface 2
( 1, 0, 0), # surface 3
( 0, 1, 0), # surface 4
( 0, -1, 0) # surface 5
]
并在绘制对象时设置合适的法向量:
def Cube():
glBegin(GL_QUADS)
for i_surface, surface in enumerate(surfaces):
x = 0
glNormal3fv(normals[i_surface]) # set the normal vector the vertices of the surface
for vertex in surface:
x+=1
glColor3fv(colors[x])
glVertex3fv(verticies[vertex])
glEnd()
glColor3fv(colors[0])
glBegin(GL_LINES)
for edge in edges:
for vertex in edge:
glVertex3fv(verticies[vertex])
glEnd()
启用 Depth Test (glEnable(GL_DEPTH_TEST)
) 以获得如下动画:
完整示例代码:
import pygame
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GLU import *
verticies = (
( 1, -1, -1), # 0
( 1, 1, -1), # 1
(-1, 1, -1), # 2
(-1, -1, -1), # 3
( 1, -1, 1), # 4
( 1, 1, 1), # 5
(-1, -1, 1), # 6
(-1, 1, 1), # 7
)
surfaces = (
(0,1,2,3),
(3,2,7,6),
(6,7,5,4),
(4,5,1,0),
(1,5,7,2),
(4,0,3,6),
)
normals = [
( 0, 0, -1), # surface 0
(-1, 0, 0), # surface 1
( 0, 0, 1), # surface 2
( 1, 0, 0), # surface 3
( 0, 1, 0), # surface 4
( 0, -1, 0) # surface 5
]
colors = (
(1,1,1),
(0,1,0),
(0,0,1),
(0,1,0),
(0,0,1),
(1,0,1),
(0,1,0),
(1,0,1),
(0,1,0),
(0,0,1),
)
edges = (
(0,1),
(0,3),
(0,4),
(2,1),
(2,3),
(2,7),
(6,3),
(6,4),
(6,7),
(5,1),
(5,4),
(5,7),
)
def Cube():
glBegin(GL_QUADS)
for i_surface, surface in enumerate(surfaces):
x = 0
glNormal3fv(normals[i_surface])
for vertex in surface:
x+=1
glColor3fv(colors[x])
glVertex3fv(verticies[vertex])
glEnd()
glColor3fv(colors[0])
glBegin(GL_LINES)
for edge in edges:
for vertex in edge:
glVertex3fv(verticies[vertex])
glEnd()
def main():
global surfaces
pygame.init()
display = (800, 600)
pygame.display.set_mode(display, DOUBLEBUF|OPENGL)
clock = pygame.time.Clock()
glMatrixMode(GL_PROJECTION)
gluPerspective(45, (display[0]/display[1]), 0.1, 50.0)
glMatrixMode(GL_MODELVIEW)
glTranslatef(0, 0, -5)
#glLight(GL_LIGHT0, GL_POSITION, (0, 0, 1, 0)) # directional light from the front
glLight(GL_LIGHT0, GL_POSITION, (5, 5, 5, 1)) # point light from the left, top, front
glLightfv(GL_LIGHT0, GL_AMBIENT, (0, 0, 0, 1))
glLightfv(GL_LIGHT0, GL_DIFFUSE, (1, 1, 1, 1))
glEnable(GL_DEPTH_TEST)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
glEnable(GL_LIGHTING)
glEnable(GL_LIGHT0)
glEnable(GL_COLOR_MATERIAL)
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE )
glRotatef(1, 3, 1, 1)
Cube()
glDisable(GL_LIGHT0)
glDisable(GL_LIGHTING)
glDisable(GL_COLOR_MATERIAL)
pygame.display.flip()
clock.tick(60)
main()
我正在学习 https://pythonprogramming.net/opengl-pyopengl-python-pygame-tutorial/ 中提供的教程,他在那里教授如何使用 pyOpenGL 渲染立方体 pygame。
渲染立方体时,教程为立方体的所有顶点设置颜色,然后显示。但是,在我的项目中,我使用 https://www.pygame.org/wiki/OBJFileLoader 中提供的代码从 .obj 文件加载对象,并且我的大部分对象都是完全白色的。
结论:当我在屏幕上渲染时,我只看到全白,非常难看。所以我想用光来更好地观察物体,但我做不到。
我对 pyOpenGl 知之甚少,找不到更深入的教程。
这里是教程中提供的部分代码和结果。 (顶点、边、表面和颜色变量是元组的元组)
def Cube():
glBegin(GL_QUADS)
for surface in surfaces:
x = 0
for vertex in surface:
x+=1
glColor3fv(colors[x])
glVertex3fv(verticies[vertex])
glEnd()
glBegin(GL_LINES)
for edge in edges:
for vertex in edge:
glVertex3fv(verticies[vertex])
glEnd()
def main():
pygame.init()
display = (800,600)
pygame.display.set_mode(display, DOUBLEBUF|OPENGL)
gluPerspective(45, (display[0]/display[1]), 0.1, 50.0)
glTranslatef(0.0,0.0, -5)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
glRotatef(1, 3, 1, 1)
Cube()
pygame.display.flip()
pygame.time.wait(10)
main()
def main():
pygame.init()
display = (800,600)
pygame.display.set_mode(display, DOUBLEBUF|OPENGL)
gluPerspective(45, (display[0]/display[1]), 0.1, 50.0)
glTranslatef(0.0,0.0, -5)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
glRotatef(1, 3, 1, 1)
glEnable(GL_LIGHTING)
glEnable(GL_LIGHT0)
glPushMatrix()
glTranslatef(0.0,0.0, 5)
glLight(GL_LIGHT0, GL_POSITION, (0, 1, 0, 1))
glLightfv(GL_LIGHT0, GL_AMBIENT, (0, 1.5, 1, 0))
glPopMatrix()
Cube()
glDisable(GL_LIGHT0)
glDisable(GL_LIGHTING)
pygame.display.flip()
pygame.time.wait(10)
我想要的是带有颜色并被灯光照亮的立方体。我的代码有什么问题以及如何修复它?
点亮时(GL_LIGHTING
) is enabled, then the color is taken from the material parameters (glMaterial
)。
如果您仍想使用当前颜色,则必须启用 GL_COLOR_MATERIAL
并设置颜色 material 参数 (glColorMaterial
).
环境光不依赖于光源的方向。您必须定义漫射 and/or 镜面光。见 glLightfv
:
当灯光位置由glLightfv(GL_LIGHT0, GL_POSITION, pos)
设置时,则该位置乘以当前模型视图矩阵。因此必须在模型转换之前设置 world space 中的光照位置。
在设置投影矩阵之前切换到矩阵模式GL_PROJECTION
。否则,光源位置将乘以投影矩阵。
glMatrixMode(GL_PROJECTION)
gluPerspective(45, (display[0]/display[1]), 0.1, 50.0)
glMatrixMode(GL_MODELVIEW)
glTranslatef(0, 0, -5)
#glLight(GL_LIGHT0, GL_POSITION, (0, 0, 1, 0)) # directional light from the front
glLight(GL_LIGHT0, GL_POSITION, (5, 5, 5, 1)) # point light from the left, top, front
glLightfv(GL_LIGHT0, GL_AMBIENT, (0, 0, 0, 1))
glLightfv(GL_LIGHT0, GL_DIFFUSE, (1, 1, 1, 1))
glEnable(GL_DEPTH_TEST)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
glEnable(GL_LIGHTING)
glEnable(GL_LIGHT0)
glEnable(GL_COLOR_MATERIAL)
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE )
glRotatef(1, 3, 1, 1)
Cube()
glDisable(GL_LIGHT0)
glDisable(GL_LIGHTING)
glDisable(GL_COLOR_MATERIAL)
pygame.display.flip()
漫射(和镜面反射)光取决于表面的 Normal 矢量。
定义一个法向量元组数组(x, y, z)
。注意下面的定义是一个例子。因为你画了一个有 6 个面的立方体,你必须定义 6 个法向量,但是向量的方向取决于你的顶点坐标,我不知道。
normals = [
( 0, 0, -1), # surface 0
(-1, 0, 0), # surface 1
( 0, 1, 1), # surface 2
( 1, 0, 0), # surface 3
( 0, 1, 0), # surface 4
( 0, -1, 0) # surface 5
]
并在绘制对象时设置合适的法向量:
def Cube():
glBegin(GL_QUADS)
for i_surface, surface in enumerate(surfaces):
x = 0
glNormal3fv(normals[i_surface]) # set the normal vector the vertices of the surface
for vertex in surface:
x+=1
glColor3fv(colors[x])
glVertex3fv(verticies[vertex])
glEnd()
glColor3fv(colors[0])
glBegin(GL_LINES)
for edge in edges:
for vertex in edge:
glVertex3fv(verticies[vertex])
glEnd()
启用 Depth Test (glEnable(GL_DEPTH_TEST)
) 以获得如下动画:
完整示例代码:
import pygame
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GLU import *
verticies = (
( 1, -1, -1), # 0
( 1, 1, -1), # 1
(-1, 1, -1), # 2
(-1, -1, -1), # 3
( 1, -1, 1), # 4
( 1, 1, 1), # 5
(-1, -1, 1), # 6
(-1, 1, 1), # 7
)
surfaces = (
(0,1,2,3),
(3,2,7,6),
(6,7,5,4),
(4,5,1,0),
(1,5,7,2),
(4,0,3,6),
)
normals = [
( 0, 0, -1), # surface 0
(-1, 0, 0), # surface 1
( 0, 0, 1), # surface 2
( 1, 0, 0), # surface 3
( 0, 1, 0), # surface 4
( 0, -1, 0) # surface 5
]
colors = (
(1,1,1),
(0,1,0),
(0,0,1),
(0,1,0),
(0,0,1),
(1,0,1),
(0,1,0),
(1,0,1),
(0,1,0),
(0,0,1),
)
edges = (
(0,1),
(0,3),
(0,4),
(2,1),
(2,3),
(2,7),
(6,3),
(6,4),
(6,7),
(5,1),
(5,4),
(5,7),
)
def Cube():
glBegin(GL_QUADS)
for i_surface, surface in enumerate(surfaces):
x = 0
glNormal3fv(normals[i_surface])
for vertex in surface:
x+=1
glColor3fv(colors[x])
glVertex3fv(verticies[vertex])
glEnd()
glColor3fv(colors[0])
glBegin(GL_LINES)
for edge in edges:
for vertex in edge:
glVertex3fv(verticies[vertex])
glEnd()
def main():
global surfaces
pygame.init()
display = (800, 600)
pygame.display.set_mode(display, DOUBLEBUF|OPENGL)
clock = pygame.time.Clock()
glMatrixMode(GL_PROJECTION)
gluPerspective(45, (display[0]/display[1]), 0.1, 50.0)
glMatrixMode(GL_MODELVIEW)
glTranslatef(0, 0, -5)
#glLight(GL_LIGHT0, GL_POSITION, (0, 0, 1, 0)) # directional light from the front
glLight(GL_LIGHT0, GL_POSITION, (5, 5, 5, 1)) # point light from the left, top, front
glLightfv(GL_LIGHT0, GL_AMBIENT, (0, 0, 0, 1))
glLightfv(GL_LIGHT0, GL_DIFFUSE, (1, 1, 1, 1))
glEnable(GL_DEPTH_TEST)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
glEnable(GL_LIGHTING)
glEnable(GL_LIGHT0)
glEnable(GL_COLOR_MATERIAL)
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE )
glRotatef(1, 3, 1, 1)
Cube()
glDisable(GL_LIGHT0)
glDisable(GL_LIGHTING)
glDisable(GL_COLOR_MATERIAL)
pygame.display.flip()
clock.tick(60)
main()