代码之家  ›  专栏  ›  技术社区  ›  appas

GLSL中的多个纹理-只有一个可用

  •  21
  • appas  · 技术社区  · 15 年前

    我的问题是在GLSL着色器中获取多个可访问的纹理。

    着色器:

    uniform sampler2D sampler0;
    uniform sampler2D sampler1;
    uniform float blend;
    void main( void )
    {
        vec2 coords = gl_TexCoord[0];
        vec4 col = texture2D(sampler0, coords);
        vec4 col2 = texture2D(sampler1, coords);
        if (blend > 0.5){
            gl_FragColor = col;
        } else {
            gl_FragColor = col2;
        }
    };
    

    当blend<=0.5时 .

    OpenGL代码:

    m_sampler0location = m_shader.FindUniform("sampler0");
    m_sampler1location = m_shader.FindUniform("sampler1");
    m_blendlocation = m_shader.FindUniform("blend");
    
    glActiveTexture(GL_TEXTURE0);
    glEnable(GL_TEXTURE_2D);
    m_extensions.glUniform1iARB(m_sampler0location, 0);
    glBindTexture(GL_TEXTURE_2D, Texture0.Handle);  
    glActiveTexture(GL_TEXTURE1);
    glEnable(GL_TEXTURE_2D);
    m_extensions.glUniform1iARB(m_sampler1location, 1);
    glBindTexture(GL_TEXTURE_2D, Texture1.Handle);
    glBegin(GL_QUADS);
        //lower left
        glTexCoord2f(0, 0);
        glVertex2f(-1.0, -1.0);
        //upper left
        glTexCoord2f(0, maxCoords0.t);
        glVertex2f(-1.0, 1.0);
        //upper right
        glTexCoord2f(maxCoords0.s, maxCoords0.t);
        glVertex2f(1.0, 1.0);
        //lower right
        glTexCoord2f(maxCoords0.s, 0);
        glVertex2f(1.0, -1.0);
    glEnd()
    

    正如我所说的 col 在着色器程序中,反射来自纹理的片段;的值 col2 是黑色的。显示的纹理是最后一个活动的纹理-如果我更改最后一个 glBindTexture Texture0.Handle ,纹理会发生变化。 根据巴巴尔的回复修正。

    事实上,即使我添加了类似 gl_FragColor.r = blend; glActiveTexture(GL_TEXTURE1); ,着色器再次工作,并且相同的纹理同时出现在sampler0和sampler1中。

    发生什么事?有问题的线路, ,似乎工作得很好,后续的 glGetIntegerv(GL_ACTIVE_TEXTURE, &anint)

    5 回复  |  直到 13 年前
        1
  •  22
  •   bosmacs    12 年前

    下面是一个基本的GLUT示例(写在OSX上,根据需要进行调整),它生成两个棋盘纹理,加载一个带有两个采样器的着色器,并通过着色(一个红色,一个蓝色)和混合来组合它们。看看这是否适合你:

    #include <stdio.h>
    #include <stdlib.h>
    
    #include <GLUT/glut.h>
    #include <OpenGL/gl.h>
    #include <OpenGL/glu.h>
    
    #define kTextureDim 64
    
    GLuint t1;
    GLuint t2;
    
    /* adapted from the red book */
    GLuint makeCheckTex() {
        GLubyte image[kTextureDim][kTextureDim][4]; // RGBA storage
    
        for (int i = 0; i < kTextureDim; i++) {
            for (int j = 0; j < kTextureDim; j++) {
                int c = ((((i & 0x8) == 0) ^ ((j & 0x8)) == 0))*255;
                image[i][j][0]  = (GLubyte)c;
                image[i][j][1]  = (GLubyte)c;
                image[i][j][2]  = (GLubyte)c;
                image[i][j][3]  = (GLubyte)255;
            }
        }
    
        GLuint texName;
        glGenTextures(1, &texName);    
        glBindTexture(GL_TEXTURE_2D, texName);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTextureDim, kTextureDim, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
    
        return texName;
    }
    
    void loadShader() {
    #define STRINGIFY(A) #A
    
        const GLchar* source = STRINGIFY(
    
                                         uniform sampler2D tex1;
                                         uniform sampler2D tex2;
    
                                         void main() {
                                             vec4 s1 = texture2D(tex1, gl_TexCoord[0].st);
                                             vec4 s2 = texture2D(tex2, gl_TexCoord[0].st + vec2(0.0625, 0.0625));
                                             gl_FragColor = mix(vec4(1, s1.g, s1.b, 0.5), vec4(s2.r, s2.g, 1, 0.5), 0.5);
                                         }
    
                                         );
    
        GLuint program = glCreateProgram();
        GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
        glShaderSource(shader, 1, &source, NULL);
        glCompileShader(shader);
    
        GLint logLength;
        glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength);
        if (logLength > 0) {
            GLchar* log = (GLchar*)malloc(logLength);
            glGetShaderInfoLog(shader, logLength, &logLength, log);
            printf("Shader compile log:\n%s\n", log);
            free(log);
        }
    
        glAttachShader(program, shader);  
        glLinkProgram(program);
    
        glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
        if (logLength > 0) {
            GLchar* log = (GLchar*)malloc(logLength);
            glGetProgramInfoLog(program, logLength, &logLength, log);
            printf("Program link log:\n%s\n", log);
            free(log);
        }
    
        GLuint t1Location = glGetUniformLocation(program, "tex1");
        GLuint t2Location = glGetUniformLocation(program, "tex2");
    
        glUniform1i(t1Location, 0);
        glUniform1i(t2Location, 1);
    
        glUseProgram(program);
    }
    
    
    void init()
    {
        glClearColor(0.0, 0.0, 0.0, 0.0);
        glEnable(GL_DEPTH_TEST);
        glShadeModel(GL_FLAT);
    
        t1 = makeCheckTex();
        t2 = makeCheckTex();
    
        loadShader();
    }
    
    
    void display()
    {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glLoadIdentity();
    
        glActiveTexture(GL_TEXTURE0);
        glEnable(GL_TEXTURE_2D);
        glBindTexture(GL_TEXTURE_2D, t1);
    
        glActiveTexture(GL_TEXTURE1);
        glBindTexture(GL_TEXTURE_2D, t2);
    
        glBegin(GL_QUADS);
        //lower left
        glTexCoord2f(0, 0);
        glVertex2f(-1.0, -1.0);
        //upper left
        glTexCoord2f(0, 1.0);
        glVertex2f(-1.0, 1.0);
        //upper right
        glTexCoord2f(1.0, 1.0);
        glVertex2f(1.0, 1.0);
        //lower right
        glTexCoord2f(1.0, 0);
        glVertex2f(1.0, -1.0);
        glEnd();
    
        glutSwapBuffers();
    }
    
    
    void reshape(int w, int h)
    {
        glViewport(0, 0, w, h);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrtho(-2, 2, -2, 2, -2, 2);
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
    }
    
    
    int main(int argc, char **argv)
    {
        glutInit(&argc, argv);
    
        glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH | GLUT_RGBA);
    
        glutInitWindowSize(512, 512);
        glutInitWindowPosition(0, 0);
    
        glutCreateWindow("GLSL Texture Blending");
    
        glutReshapeFunc(reshape);
        glutDisplayFunc(display);
        glutIdleFunc(display);
    
        init();
    
        glutMainLoop();
        return 0;
    }
    

    希望结果会像这样(你可以注释掉 glUseProgram 调用以查看在没有着色器的情况下绘制的第一个纹理): alt text

        2
  •  12
  •   Jérémy Riviere    12 年前

    只是为了帮助其他人谁可能有兴趣使用多种纹理,并会觉得无望后,天搜索一个答案。我发现你需要打电话

    glUseProgram(program);
    
    GLuint t1Location = glGetUniformLocation(program, "tex1");
    GLuint t2Location = glGetUniformLocation(program, "tex2");
    
    glUniform1i(t1Location, 0);
    glUniform1i(t2Location, 1);
    

        3
  •  9
  •   fancyPants    13 年前

    很晚才回复,但对于任何遇到这种情况的人来说——我也遇到了同样的问题,经过短暂的调整后,我意识到 glActiveTexture(GL_TEXTURE0) 解决了这个问题。 如果活动纹理单元没有被“重置”为零,那么接下来的事情似乎会变得混乱。 能够

        4
  •  2
  •   bosmacs    15 年前

    编译着色器进行测试时,我发现两个错误:

    1. coords 应分配 st 四分量部分 gl_TexCoord ,例如。

      vec2 coords = gl_TexCoord[0].st;
      
    2. 着色器不应以分号结尾。

    你在主程序的任何地方检查着色器编译是否正确吗?你可以看看 GL_COMPILE_STATUS 通过 glGetShader glGetShaderInfoLog .

        5
  •  0
  •   Bahbar    15 年前

    glActiveTexture 呼叫不起作用。是否确定已正确设置函数指针?

    通过调用验证 glGetIntegerv(GL_ACTIVE_TEXTURE, &anint) 在调用了glActiveTexture(GL\u TEXTURE1)之后。

    阿尔索 glEnable(GL_TEXTURE_2D) 都没用。着色器本身指定要使用的纹理单元,以及每个单元中要“启用”的目标。


    编辑以添加:

    嗯,你的新情况很特别。事实上,你甚至不能显示红色是奇怪的,特别是(好吧,你设置阿尔法为1只是为了确保?)。

    玻璃结构 设置完纹理单元1后(即 glBindTexture 电话)。