The lighting in the OpenGL only goes towards the left in the sphere, even though there was no way that the light could have reached there because it was to the right of the sphere. The light also goes towards the back for the cube, but it should go toward every direction because it is in the middle of the cube. How do I make the light go in every direction instead of one?
Full code:
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)
The cube is the light source and in the center of the scene. The sphere is at the left of the cube and lit form the right. This seems correct. Note that the light is not blocked by an object. The light depends on the normal vector of the surface. Therefor you need to set the normal vector with 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()
# [...]
The surfaces are only illuminated if the direction of the light vector is opposite to the direction of the normal vector. If you als want the backfaces a illuminated you need to set GL_LIGHT_MODEL_TWO_SIDE
(see glLightModelfv
):
glLightModeliv(GL_LIGHT_MODEL_TWO_SIDE, 1)