Search code examples
pythonopenglpygamepyopengl

How to use lighting when using glOrtho?


I'm trying to activate lighting over a spherical object in pyopengl-pygame. I'm using glOrtho to project my object but the ligthing is not working. I found some clues on the web but the aproach is too matricial and although i understand the principles about matrix, i don't know how to use the OpenGL code correctly.

This is my code. What is wrong with my ligthing code?. Thanks.

import pygame
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
#<some other libraries imports>

def sup_texture(surf):
    rgbsurf = pygame.image.tostring(surf, 'RGB')
    textID = glGenTextures(1)
    glBindTexture(GL_TEXTURE_2D, texID)
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
    surfrc = surf.get_rect()
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, surfrc[2], surfrc[3], 0, GL_RGB, GL_UNSIGNED_BYTE, rgbsurf)
    return textID

def texture(arch,arch2):
    textID = glGenTextures(1)
    glBindTexture(GL_TEXTURE_2D, textID)
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR)
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL)
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,arch2[0], arch2[1], 0, GL_RGB, GL_UNSIGNED_BYTE, arch)
    glGenerateMipmap(GL_TEXTURE_2D)
    return textID

def oglprint(sup):
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    glDisable(GL_LIGHTING)
    glEnable(GL_TEXTURE_2D)
    glBindTexture(GL_TEXTURE_2D, sup)
    glBegin(GL_QUADS)
    glTexCoord2f(0, 0); glVertex2f(-1, 1)
    glTexCoord2f(0, 1); glVertex2f(-1, -1)
    glTexCoord2f(1, 1); glVertex2f(1, -1)
    glTexCoord2f(1, 0); glVertex2f(1, 1)
    glEnd()
    glDisable(GL_TEXTURE_2D)

def esfep(vesf,resol,texture,rotpt,punt,tama):
    light_ambient =  [0.0, 0.0, 0.0, 1.0]
    light_diffuse =  [1.0, 1.0, 1.0, 1.0]
    light_specular =  [1.0, 1.0, 1.0, 1.0]
    light_position =  [resol[0]/2, resol[1]/2, -resol[1], 0.0]
    glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient)
    glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse)
    glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular)
    glLightfv(GL_LIGHT0, GL_POSITION, light_position)
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    rotpt = rotpt + vesf  
    glOrtho(0,resol[0],resol[1],0,-resol[0],resol[1])
    glTranslatef(float(punt[0]),float(punt[1]),-resol[1]) 
    glRotatef(270, 1, 0, 0)
    glRotatef(rotpt, 0, 0, 1)
    glScalef(1*tama/resol[1],1*tama/resol[1],1*tama/resol[1])
    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity()
    glEnable(GL_LIGHTING)
    glEnable(GL_LIGHT0)
    glEnable(GL_COLOR_MATERIAL)
    glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE )
    esf = gluNewQuadric()
    gluQuadricTexture(esf, GL_TRUE)
    glDisable(GL_DEPTH_TEST)
    glEnable(GL_TEXTURE_2D)
    glBindTexture(GL_TEXTURE_2D, texture)
    gluSphere(esf,round(resol[1]/2), 50, 50)
    gluDeleteQuadric(esf)
    glDisable(GL_TEXTURE_2D)
    glDisable(GL_DEPTH_TEST) 
    return rotpt 

pygame.init()

resol = (1366,768)
opcp = pygame.HWSURFACE | pygame.DOUBLEBUF | pygame.OPENGL | pygame.FULLSCREEN
displayG = pygame.display.set_mode(resol,opcp)
display = pygame.Surface(resol)

imgpl = pygame.image.load('texture.jpg')
imgplt = imgpl.get_size()
imgpl = pygame.transform.smoothscale(imgpl,(1000,500))
imgpltd = pygame.image.tostring(imgpl,'RGB',False)
planpres = texture(imgpltd,imgplt) #Obtaining the texture for blitting
rotpt = randint(270,360)
timer = pygame.time.Clock()
RE = tab(display)
while True:                
    #<some pygame stuff and display blitting>
    opsurf = pygame.Surface.copy(display)
    pantsp = sup_texture(opsurf) #obtaining 2D texture copying from pygame surface
    botact = 1
    while botact == 1:
        timer.tick(20) 
        oglprint(pantsp) #printing the 2D: text, some images...                  
        rotpt = esfep(0.05,resol,planpres,rotpt,(0,resol[1] + resol[1]/4.5),1000)  #this is the printing of the sphere. 
        pygame.display.flip()
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                exit() 
            elif event.type == pygame.MOUSEBUTTONDOWN:
                x_mouse, y_mouse = pygame.mouse.get_pos()
                dot = (x_mouse,y_mouse)
                for x in range(len(RE)):
                    if RE[x].collidepoint(dot):
                        #<some stuff>
                        botact = 0
                        glDeleteTextures(pantsp)

Solution

  • The fact that the light doesn't work has nothing to do with the orthographic projection. It's related to the texture.
    You need to set the texture environment parameter to mix the light color and the texture color. Use GL_MODULATE to multiply the light color and the texture color:

    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE)