Pyopengl:即使在中心,照明也不会向所有方向传播

Pyopengl: Lighting does not go in all directions even though it is in the center

OpenGL 中的光照仅朝向球体的左侧,尽管光线不可能到达那里,因为它位于球体的右侧。光线也朝向立方体的背面,但它应该朝向各个方向,因为它位于立方体的中间。如何让光线朝各个方向而不是一个方向照射?

完整代码:

import random
import time
import pygame
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *


width = 500
height = 500
random_number = 0
turned = 0
angle = 0

switch = False

vertices = [(-0.5, -0.5, -0.5), (0.5, -0.5, -0.5), (0.5, 0.5, -0.5), (-0.5, 0.5, -0.5), (-0.5, -0.5, 0.5), (0.5, -0.5, 0.5), (0.5, 0.5, 0.5), (-0.5, 0.5, 0.5)]
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)]
colors = [(1, 0, 0), (0, 1, 0), (0, 0, 1), (1, 1, 0), (1, 0, 1), (0, 1, 1)]


def draw_shapes():
    global turned, switch, random_number, angle
    glDisable(GL_TEXTURE_2D)
    glPushMatrix()

    if turned >= 90:
        random_number = random.randint(0, 2)
        turned = angle = 0

    if random_number == 0:
        glRotatef(angle, 0, 1, 0)
    elif random_number == 1:
        glRotatef(angle, 1, 0, 0)
    else:
        glRotatef(angle, 0, 0, 1)

    turned += 1
    angle += 1
    # glColor3fv((.16, .16, .16))

    glBegin(GL_QUADS)
    for i, face in enumerate(faces):
        for surftex, vertex in enumerate(face):
            if surftex == 0:
                glTexCoord2f(1.0, 1.0)
            elif surftex == 1:
                glTexCoord2f(1.0, 0.0)
            elif surftex == 2:
                glTexCoord2f(0.0, 0.0)
            elif surftex == 3:
                glTexCoord2f(0.0, 1.0)
            glVertex3fv(vertices[vertex])
    glEnd()

    glPopMatrix()
    glDisable(GL_TEXTURE_2D)
    glPushMatrix()
    # glColor3fv((.16, .16, .16))
    glTranslatef(-3, 0, 0)
    Quadric = gluNewQuadric()
    gluSphere(Quadric, 1, 50, 50)
    glPopMatrix()





def showScreen():
    global width, height

    glClearColor(0, 0, 0, 1)

    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)
    glLightfv(GL_LIGHT0, GL_POSITION, (0, 0, 0, 1))  # point light from the left, top, front
    glLightfv(GL_LIGHT0, GL_AMBIENT, (1, 0, 0, 1))

    glEnable(GL_DEPTH_TEST)

    draw_shapes()



    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, -7)
    # glRotatef(3, 1, 0, 0)


def keyboard(key, x_pos, y_pos):
    print(key, x_pos, y_pos)


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


while True:
    glutMainLoopEvent()

    glutPostRedisplay()

    time.sleep(0.01)

立方体是光源,位于场景的中心。球体位于立方体的左侧,并在右侧发光。这似乎是正确的。请注意,光线没有被物体阻挡。光线取决于表面的法向量。因此你需要设置法向量 glNormal (See also How does the calculation of the light model work in a shader program?):

vertices = [(-0.5, -0.5, -0.5), (0.5, -0.5, -0.5), (0.5, 0.5, -0.5), (-0.5, 0.5, -0.5), (-0.5, -0.5, 0.5), (0.5, -0.5, 0.5), (0.5, 0.5, 0.5), (-0.5, 0.5, 0.5)]
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)]
colors = [(1, 0, 0), (0, 1, 0), (0, 0, 1), (1, 1, 0), (1, 0, 1), (0, 1, 1)]
textureCoords = [(1, 1), (1, 0), (0, 0), (0, 1)]
normals = [(-1, 0, 0), (0, -1, 0), (0, 0, -1), (1, 0, 0), (0, 1, 0), (0, 0, 1)]
def draw_shapes():
    # [...]

    glBegin(GL_QUADS)
    for i, face in enumerate(faces):
        glNormal3fv(normals[i])
        for surftex, vertex in enumerate(face):
            glTexCoord2fv(textureCoords[surftex])
            glVertex3fv(vertices[vertex])
    glEnd()

    # [...]

仅当光矢量的方向与法线矢量的方向相反时,表面才会被照亮。如果您还希望背面发光,则需要设置 GL_LIGHT_MODEL_TWO_SIDE(参见 glLightModelfv):

glLightModeliv(GL_LIGHT_MODEL_TWO_SIDE, 1)