使用GLSL着色器在PyOpenGL中进行多纹理化

时间:2012-07-10 11:27:12

标签: python opengl glsl textures pyopengl

我希望能够在GLSL片段着色器中组合两个纹理。我目前正在使用PyOpenGL,到目前为止,使用着色器完成的所有工作都运行良好。

当我尝试从片段着色器访问多个纹理时遇到困难,例如,以下着色器显示正确的纹理减去蓝色像素:

uniform sampler2D my_texture1;
uniform sampler2D my_texture2;
void main()
{
    vec4 color1 = texture2D(my_texture1, gl_TexCoord[1].st);
    vec4 color2 = texture2D(my_texture2, gl_TexCoord[2].st);
    if (color1.b > 0.8)
        discard;
    gl_FragColor = color1;
}

但是

uniform sampler2D my_texture1;
uniform sampler2D my_texture2;
void main()
{
    vec4 color1 = texture2D(my_texture1, gl_TexCoord[1].st);
    vec4 color2 = texture2D(my_texture2, gl_TexCoord[2].st);
    if (color2.b > 0.8)
        discard;
    gl_FragColor = color2;
}

导致黑屏。

我有一种感觉,问题可能在于我如何将纹理制服传递到着色器,但是对于我的生活无法解决为什么第一个纹理有效而第二个纹理没有效果。以下是完整的计划。

from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
from Image import *
from OpenGL.GL.shaders import *

ESCAPE = '\033'
global size
size = 512

def drawQuad(B,T,L,R):
    glBegin(GL_QUADS)
    glMultiTexCoord2f(GL_TEXTURE1, 0.0, 0.0); glMultiTexCoord2f(GL_TEXTURE2, 0.0, 0.0); glVertex3f(B, L,  1.0);       ## Bottom Left Of The Texture and Quad
    glMultiTexCoord2f(GL_TEXTURE1, 1.0, 0.0); glMultiTexCoord2f(GL_TEXTURE2, 1.0, 0.0); glVertex3f( T, L,  1.0);       ## Bottom Right Of The Texture and Quad
    glMultiTexCoord2f(GL_TEXTURE1, 1.0, 1.0); glMultiTexCoord2f(GL_TEXTURE2, 1.0, 1.0); glVertex3f( T,  R,  1.0);       ## Top Right Of The Texture and Quad
    glMultiTexCoord2f(GL_TEXTURE1, 0.0, 1.0); glMultiTexCoord2f(GL_TEXTURE2, 0.0, 1.0); glVertex3f(B,  R,  1.0);       ## Top Left Of The Texture and Quad
    glEnd()

def InitGL(Width, Height):
    print "Vendor:   " + glGetString(GL_VENDOR)
    print "Renderer: " + glGetString(GL_RENDERER)
    print "OpenGL Version:  " + glGetString(GL_VERSION)
    print "Shader Version:  " + glGetString(GL_SHADING_LANGUAGE_VERSION)

    if not glUseProgram:
        print 'Missing Shader Objects!'
        sys.exit(1)

    global program
    program = compileProgram(
        compileShader('''
                void main()
                {
                    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
                    gl_TexCoord[1] = gl_MultiTexCoord1;
                    gl_TexCoord[2] = gl_MultiTexCoord2;
                }
        ''',GL_VERTEX_SHADER),
        compileShader('''
                uniform sampler2D my_texture1;
                uniform sampler2D my_texture2;
                void main()
                {
                    vec4 color1 = texture2D(my_texture1, gl_TexCoord[1].st);
                    vec4 color2 = texture2D(my_texture2, gl_TexCoord[2].st);
                    if (color1.b > 0.8)
                        discard;
                    gl_FragColor = color1;
                }
    ''',GL_FRAGMENT_SHADER),
    )

    #bmp texture 1
    image = open("rgb.bmp")
    ix = image.size[0]
    iy = image.size[1]
    image = image.tostring("raw", "RGBX", 0, -1)
    glActiveTexture(GL_TEXTURE1)
    global my_texture1
    my_texture1 = glGenTextures(1)
    glBindTexture(GL_TEXTURE_2D, my_texture1) 
    glPixelStorei(GL_UNPACK_ALIGNMENT,1)
    glTexImage2D(GL_TEXTURE_2D, 0, 3, ix, iy, 0, GL_RGBA, GL_UNSIGNED_BYTE, image)
    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)
    glGenerateMipmap(GL_TEXTURE_2D)

    #bmp texture 2
    image = open("rgb2.bmp")
    ix = image.size[0]
    iy = image.size[1]
    image = image.tostring("raw", "RGBX", 0, -1)
    glActiveTexture(GL_TEXTURE2)
    global my_texture2
    my_texture2 = glGenTextures(1)
    glBindTexture(GL_TEXTURE_2D, my_texture2) 
    glPixelStorei(GL_UNPACK_ALIGNMENT,1)
    glTexImage2D(GL_TEXTURE_2D, 0, 3, ix, iy, 0, GL_RGBA, GL_UNSIGNED_BYTE, image)
    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)
    glGenerateMipmap(GL_TEXTURE_2D)

def DrawGLScene():
    global frame, testvar, my_texture1,my_texture2
    glEnable(GL_TEXTURE_2D)
    glBindTexture(GL_TEXTURE_2D, 0)
    glUseProgram(program)
    myUniformLocation1 = glGetUniformLocation(program, "my_texture1")
    glUniform1i(myUniformLocation1, 1)
    myUniformLocation2 = glGetUniformLocation(program, "my_texture2")
    glUniform1i(myUniformLocation2, 2)
    glViewport(0, 0, size,size)
    glClearDepth(1.0)
    glClearColor (0.0, 0.0, 0.0, 1.0)
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()  
    glOrtho(-1, 1, -1, 1, -30.0, 30.0)
    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity() 
    glEnable(GL_DEPTH_TEST)
    drawQuad(-1.0,1.0,-1.0,1.0)
    glutSwapBuffers()

def keyPressed(*args):
    global texturenumber, shadernumber, frame
    # If escape is pressed, kill everything.
    if args[0] == ESCAPE:
        sys.exit()

def main():
    global window
    glutInit(sys.argv)
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH)
    glutInitWindowSize(size,size)
    glutInitWindowPosition(0, 0)
    window = glutCreateWindow("Multitexturing")
    glutDisplayFunc(DrawGLScene)
    glutIdleFunc(DrawGLScene)
    glutKeyboardFunc(keyPressed)
    InitGL(size,size)
    glutMainLoop()

if __name__ == "__main__":
    print "Press 'ESC' key to quit."
    main()

1 个答案:

答案 0 :(得分:1)

在使用之前,你实际上解开了第二个纹理:

def DrawGLScene():
    global frame, testvar, my_texture1,my_texture2
    glEnable(GL_TEXTURE_2D)
    glBindTexture(GL_TEXTURE_2D, 0)
    [...]

初始化后,纹理单元1已分配my_texture1,纹理单元2 my_texture2。活动纹理仍然是纹理2.因此,通过调用glBindTexture(GL_TEXTURE_2D, 0),您可以从活动纹理单元2取消绑定纹理。

你要做的是:

def DrawGLScene():
    global frame, testvar, my_texture1,my_texture2
    glActiveTexture(GL_TEXTURE1)
    glBindTexture(GL_TEXTURE_2D, my_texture1) 
    glActiveTexture(GL_TEXTURE2)
    glBindTexture(GL_TEXTURE_2D, my_texture2)
    [...]

您也可以简单地删除最后四行(global frame, testvar, my_texture1,my_texture2之后),因为您的init例程会处理此问题。但是,如果在代码中绑定和取消绑定任何其他纹理,则必须按上述方式执行纹理单元激活和纹理绑定。