如何使用pygame和pyopengl正确添加灯光以使对象获得更好的视图 [英] How to correctly add a light to make object get a better view with pygame and pyopengl

查看:209
本文介绍了如何使用pygame和pyopengl正确添加灯光以使对象获得更好的视图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在关注 https://pythonprogramming.net/opengl中提供的教程-pyopengl-python-pygame-tutorial/,他在那里教如何使用pyOpenGL将立方体渲染为pygame.

I am following the tutorial available in https://pythonprogramming.net/opengl-pyopengl-python-pygame-tutorial/ where he teachs how to render a cube with pyOpenGL an pygame.

渲染多维数据集时,本教程将颜色设置为多维数据集的所有顶点,然后将其分配.但是,在我的项目中,我使用 https://www中提供的代码从.obj文件加载对象. .pygame.org/wiki/OBJFileLoader ,我的大多数对象都是白色的.

When rendering the cube, the tutorial set color to all the vertices of the cubes and then dispays it. However, im my project, i load object from a .obj file using the code provided in https://www.pygame.org/wiki/OBJFileLoader and most of my objects is fully white.

结论:当我在屏幕上渲染它时,我只会看到全白,这非常丑陋.因此,我努力使用灯光更好地查看对象,但是我无法完成这项工作.

Conclusion: when i render it on screen, i only see full white, which is very ugly. So i tought to use a light to better view the object, but i cannot make this work.

我对pyOpenGl知之甚少,我找不到更深入的教程.

I know very little of pyOpenGl and i cannot find a deeper tutorial of it.

这是代码的一部分,以及本教程中提供的结果. (顶点,边,表面和颜色变量是元组的元组)

Here is part of the code and the result provided in the tutorial. (vertices, edges, surfaces and color variables are tuple of tuples)

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()

我试图编辑main函数以插入简单的灯光,但是立方体中的颜色消失了:

i tried to edit the main function to insert a simple light, but the colors in the cube just disapeared:

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)

我想要的是具有颜色并被灯光照亮的立方体.我的代码有什么问题以及如何解决?

What i want is the cube with its colors and iluminated by a light. What is wrong with my code and how to fix it?

推荐答案

照明时(

When lighting (GL_LIGHTING) is enabled, then the color is taken from the material parameters (glMaterial).

如果您仍要使用当前颜色,则必须启用 GL_COLOR_MATERIAL 并设置颜色材料参数( glColorMaterial ).

If you still want to use the current color, the you have to enable GL_COLOR_MATERIAL and to set the color material paramters (glColorMaterial).

环境光不取决于光源的方向.您必须定义一个漫反射和/或镜面反射光.参见 glLightfv :

The ambient light does not depend on the the direction of the light source. You've to define a diffuse and/or specular light. See glLightfv:

当灯光位置由 ,然后将该位置乘以当前模型视图矩阵.因此,必须在模型转换之前设置世界空间中的灯光位置. 在设置投影矩阵之前,请切换到矩阵模式GL_PROJECTION.否则,光的位置将乘以投影矩阵.

When the light position is set by glLightfv(GL_LIGHT0, GL_POSITION, pos), then the position is multiplied by the current model view matrix. So the light position in world space has to be set before the model transformation. Switch to the matrix mode GL_PROJECTION, before the projection matrix is set. Otherwise the light position would be multiplied by the projection matrix.

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()

漫射(和镜面反射)光取决于的法线向量表面.

The diffuse (and specular) light depends on the Normal vector of the surface.

定义法线向量元组(x, y, z)的数组.请注意,以下定义是一个示例.由于绘制了具有6个面的立方体,因此必须定义6个法线向量,但是向量的方向取决于您的顶点坐标,我不知道.

Define an array of normal vector tuples (x, y, z). Note the following definition is an example. Since you draw a cube, which has 6 faces, you've to define 6 normal vectors, but the direction of the vectors depends on your vertex coordinates, which I do not know.

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
]

并在绘制对象时设置适当的法线向量:

And set the proper normal vector when the object is drawn:

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()

启用深度测试(glEnable(GL_DEPTH_TEST))以获得类似于以下:

Enable the Depth Test (glEnable(GL_DEPTH_TEST)) to get an animation like the following:

完整的示例代码:

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()

这篇关于如何使用pygame和pyopengl正确添加灯光以使对象获得更好的视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆