Search code examples
pythonopengltexture-mappingpyopenglcolor-blending

pyopengl set multipass texture blending mode


im trying to get multi texturing working and have so far got miltiple textures to load using this function

def loadTexture(name):

    img = PIL.Image.open(name) # .jpg, .bmp, etc. also work
    img_data = numpy.array(list(img.getdata()), numpy.int8)

    id = glGenTextures(1)
    glPixelStorei(GL_UNPACK_ALIGNMENT,1)
    glBindTexture(GL_TEXTURE_2D, id)
    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_MAG_FILTER, GL_LINEAR)
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, img.size[0], img.size[1], 0, GL_RGB, GL_UNSIGNED_BYTE, img_data)
    return id

And I can set the texture to use with this code

glBindTexture(GL_TEXTURE_2D, 1)
glEnable(GL_TEXTURE_2D)

My first attempt has been this:

glBindTexture(GL_TEXTURE_2D, 1)
glEnable(GL_TEXTURE_2D)
glBegin(GL_TRIANGLES)
....
glEnd()

glBindTexture(GL_TEXTURE_2D, 3)
glEnable(GL_TEXTURE_2D)
glBegin(GL_TRIANGLES)
....
glEnd()

So i render the polys twice and select a different texture each time, this seems to work in as much as calling glBindTexture(GL_TEXTURE_2D, n) will select the relivant texture and it will render but there is no blending going on per se, i just see the last selected texture in the render. I've tried adding glEnable(GL_BLEND), but that doesn't seem to do anything.

What I would like to do is to add pixels of the two passes together

How would I go about this?


Solution

  • Are you sure that you need multiple passes? Here is an example of plain old OpenGL multitexturing:

    import pygame
    from pygame.locals import *
    
    import numpy
    import numpy.linalg
    
    from OpenGL.GL import *
    from OpenGL.GL.shaders import *
    
    RESOLUTION = (800,600)
    
    POSITIONS = numpy.array([[-1.0, -1.0], [+1.0, -1.0], [-1.0, +1.0], [+1.0, +1.0]], dtype=numpy.float32)
    TEXCOORDS = numpy.array([[0.0, 1.0], [1.0, 1.0], [0.0, 0.0], [1.0, 0.0]], dtype=numpy.float32)
    
    from PIL import Image
    
    tex0 = 0
    tex1 = 0
    
    def loadTexture(path):
        img = Image.open(path)
        img = img.convert("RGBA") 
        img_data = numpy.array(list(img.getdata()), numpy.int8)
    
        texture = glGenTextures(1)
        glPixelStorei(GL_UNPACK_ALIGNMENT,1)
        glBindTexture(GL_TEXTURE_2D, texture)
        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_MAG_FILTER, GL_LINEAR)
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img.size[0], img.size[1], 0, GL_RGBA, GL_UNSIGNED_BYTE, img_data)
    
        return texture
    
    def init():
        global tex0
        global tex1
    
        tex0 = loadTexture("texture0.png")
        tex1 = loadTexture("texture1.png")
    
        glViewport(0, 0, *RESOLUTION)
    
        aspect = RESOLUTION[0]/float(RESOLUTION[1])
    
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrtho(-aspect, +aspect, -1.0, +1.0, -1.0, +1.0);
    
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
    
        glClearColor(0.0, 0.0, 0.0, 1.0);
    
        glVertexPointer(2, GL_FLOAT, 0, POSITIONS);
        glEnableClientState(GL_VERTEX_ARRAY);
    
        glClientActiveTexture(GL_TEXTURE0);
        glTexCoordPointer(2, GL_FLOAT, 0, TEXCOORDS); 
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    
        glClientActiveTexture(GL_TEXTURE1);
        glTexCoordPointer(2, GL_FLOAT, 0, TEXCOORDS);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    
    def draw():
        glClear(GL_COLOR_BUFFER_BIT);
    
        glActiveTexture(GL_TEXTURE0);
        glEnable(GL_TEXTURE_2D);
        glBindTexture(GL_TEXTURE_2D, tex0);
        glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
    
        glActiveTexture(GL_TEXTURE1);
        glEnable(GL_TEXTURE_2D);
        glBindTexture(GL_TEXTURE_2D, tex1);
        glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    
    def main():
        pygame.init()
    
        screen = pygame.display.set_mode(RESOLUTION, OPENGL | DOUBLEBUF)
    
        init()
    
        while True:
            for event in pygame.event.get():
                if event.type == QUIT: return
    
            draw()
    
            pygame.display.flip()
    
    if __name__ == "__main__":
        main()
    

    Have a look at Texture Combiners, they may enable the type of effect you are looking for. Of course, the state of the art for this kind of thing nowadays are shaders.