当前位置: 首页 > 知识库问答 >
问题:

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

巫马化
2023-03-14

我希望能够在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个答案

滑景胜
2023-03-14

实际上,在使用第二个纹理之前,将其解除绑定:

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

初始化后,纹理第一单元已分配my\u texture1,纹理第二单元已分配my\u texture2。活动纹理仍然是纹理2。因此,通过调用glBindTexture(GL\u TEXTURE\u 2D,0)可以将纹理从活动纹理第二单元中解除绑定。

你应该做的是:

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)
    [...]

您也可以简单地删除最后四行(在全局框架、testvar、my_texture1、my_texture2之后),因为您的初始化例程会处理这一点。但是,如果您绑定和取消绑定代码中的任何其他纹理,您必须像上面一样执行纹理单元激活和纹理绑定。

 类似资料:
  • 我正在努力发送多个纹理到一个单一的着色器,并有一个奇怪的问题,在着色器中的两个采样器似乎得到相同的纹理数据。我知道还有很多其他的多纹理问题和答案(这里有一些我已经读过很多次了1,2,3),但一些bug正在逃避我,我开始失去我的弹珠。我很有信心我已经把一切都安排好了,但显然还是有一些问题。 所以,目前我有形状,材料,纹理,和着色器类。我的shape类是执行实际绘制的父类。它有一个具有着色器和纹理数组

  • 如何在平面上滚动纹理?所以我有一个平面有一个纹理,我可以使用一个着色器滚动左从右(无限)的纹理上?

  • 我在Mac OSX下工作,试图通过GLSL着色器在立方体上映射图像。 我显示立方体(以及图像,当它不通过着色器时)的方法是: 正如你所看到的,我正在检查,在这个测试中,是否有一个着色器应用到我的对象上(它是一个包装,效果非常好) 如果没有着色器,我只启用GL_纹理_坐标_数组,如果有,我尝试将图像绑定到着色器中的采样2D均匀。 我使用的着色器非常简单:它只显示纹理。我在Quartz Compose

  • 我正在做一个游戏,我现在正在写一个着色器来反射光从一个物体,我不断得到错误消息: 任何帮助都将不胜感激。

  • 下面代码中的两个字符串 vertexShaderSource和fragShaderSource 是 WebGL 的着色器代码,着色器代码通过着色器语言GLSL ES编写,对于前端工程来说学习 WebGL,还需要学习一门新的语言着色器语言GLSL ES。关于着色器语言的学习,可以跟着课程一边写案例,一边去学习,这样更容易理解。 着色器语言用于计算机图形编程,运行在GPU中,平时所说的大多数语言编写的

  • 标准着色器 Unity 标准着色器是一个内置着色器,具有非常全面的功能。它可以用于渲染『真实世界』的对象,例如,石头、木材、玻璃、塑料和金属,并支持各种各样的着色器类型和组合。通过使用或不使用材质编辑器中的各种纹理插槽和参数,可以很容易地启动或禁用其功能。 标准着色器还包括一个称为 物理着色器(Physically Based Shading,PBS) 的高级光照模型。物理着色器以模拟真实世界的方