Search code examples
pythonopengltexturespyopengl

Pyopengl: gluSphere drawn with a textured cube is colored


When I add a texture to the cube in the draw_shapes function, the sphere that is drawn after that is colored even though I did glColor3fv((1, 1, 1)). I don't know why this is, and when I remove the texture, the sphere turns back to a white color. How do I make the sphere not have any color?

Full code:

import random
import time
import pygame
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
array = [(0, 0, 0)]
width = 500
height = 500
random_number = 0
turned = 0
angle = 0
switch = False

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

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

    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()
    glPushMatrix()
    glColor3fv((1, 1, 1))
    glTranslatef(-3, 0, 0)
    Quadric = gluNewQuadric()
    gluSphere(Quadric, 1, 50, 50)
    glPopMatrix()





def textureBind():
    image = pygame.image.load("Image.png")
    datas = pygame.image.tostring(image, 'RGBA')

    glEnable(GL_TEXTURE_2D)
    texture_id = glGenTextures(1)

    glBindTexture(GL_TEXTURE_2D, texture_id)
    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE)
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER)
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER)
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image.get_width(), image.get_height(),
                 0, GL_RGBA, GL_UNSIGNED_BYTE, datas)

    return texture_id


def showScreen():
    global width, height
    glClearColor(0, 0, 0, 1)
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    draw_shapes()
    glEnable(GL_DEPTH_TEST)
    glEnable(GL_LIGHTING)
    glEnable(GL_LIGHT0)
    glEnable(GL_COLOR_MATERIAL)
    glLightfv(GL_LIGHT0, GL_POSITION, (-2, -2, 2, 1))  # point light from the left, top, front
    glLightfv(GL_LIGHT0, GL_AMBIENT, (1, 1, 1, 1))
    glutSwapBuffers()


def mouseTracker(mousex, mousey):
    print(f"Mouse pos: {mousex}, {mousey}")


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


glutInit()
glutInitDisplayMode(GLUT_RGBA)
glutInitWindowSize(500, 500)
wind = glutCreateWindow("OpenGL")
glutDisplayFunc(showScreen)
glutIdleFunc(showScreen)
glutMotionFunc(mouseTracker)
glutPassiveMotionFunc(mouseTracker)
glutReshapeFunc(reshapeWindow)
gluPerspective(45, (width / height), 0.0001, 1000)
gluNewQuadric()

while True:
    glutMainLoopEvent()
    glutPostRedisplay()
    time.sleep(0.01)

Solution

  • OpenGL is a state engine. Once a state is set it is persistent. When texturing is activated, by default the color of the texture is multiplied by the current color, because by default the texture environment mode (GL_TEXTURE_ENV_MODE) is GL_MODULATE. See glTexEnv. This causes that the color of the texture is "mixed" by the last color which you have set by glColor3f.

    You must disable texturing if you want to draw an object without texture:

    def draw_shapes():
        global turned, switch, random_number, angle
    
        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((1, 1, 1))
        glEnable(GL_TEXTURE_2D) # <--- enable
    
        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()
        glPushMatrix()
        
        glColor3fv((1, 1, 1))
        glDisable(GL_TEXTURE_2D) # <--- disable
    
        glTranslatef(-3, 0, 0)
        Quadric = gluNewQuadric()
        gluSphere(Quadric, 1, 50, 50)
        glPopMatrix()