Search code examples
pythonopenglpyqttexturespyopengl

PyQt, PyOPENGL: when adding a texture to an area, then other area lost their color and become white


This is the texture setting.

    img1 = Image.open(".\\pictures\\checkboard.jpg")
    img1_data = np.array(list(img1.getdata()), np.int8)
    glGenTextures(2)
    glBindTexture(GL_TEXTURE_2D, 2)
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
    glTexImage2D(GL_TEXTURE_2D, 0, 3, img1.size[0], img1.size[1], 0, GL_RGB, GL_UNSIGNED_BYTE, img1_data)
    # glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP)
    # glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP)
    # 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_NEAREST)
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL)

When I added this texture to an area, the bottom area became white. It is so weird, because the bottom area is set to red in my program.

    glColor3f(1, 0, 0)
    glBegin(GL_QUADS)
    glVertex3f(-0.1, 0.1, 0)
    glVertex3f(-0.1, -0.1, 0)
    glVertex3f(0.1, -0.1, 0)
    glVertex3f(0.1, 0.1, 0)
    glEnd()

Solution

  • 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.

    When the environment mode is changed to GL_DECAL then the color and the texture are mixed, based on the alpha channel of the texture.
    The mixin can be expressed as

    final_color = color * (1 - texture_color.a) + texture_color *⁢ texture_color.a
    

    or

    final_color = mix(color, texture_color, texture_color.a)
    

    If you draw a quad, without setting any texture coordinates, them all the texture coordinates are the same and have the value which was last set by glTexCoord.
    Since you get a white quad, it seems to be that the texel at the position of the texture coordinate is completely white with an alpha channel of 1 (or the texture has no alpha channel, so it is 1 by default).

    You have to disable texturing, before you draw the quad to solve your issue. See glEnable:

    glDisable(GL_TEXTURE_2D)
    glColor3f(1, 0, 0)
    glBegin(GL_QUADS)
    glVertex3f(-0.1, 0.1, 0)
    glVertex3f(-0.1, -0.1, 0)
    glVertex3f(0.1, -0.1, 0)
    glVertex3f(0.1, 0.1, 0)
    glEnd()
    glEnable(GL_TEXTURE_2D)