2010-08-25 20 views
22

我的问题是获取GLSL着色器中可以访问的多个纹理。 下面是我在做什么: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; 
    } 
}; 

所以,我只是基于一个统一的变量两种颜色值之间进行选择。足够简单(这是一个测试),但代替预期的行为,当混合< = 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,纹理会更改。 根据Bahbar的回复修复。

事实上,即使我将诸如gl_FragColor.r = blend;之类的东西添加为着色器的最后一行,场景也会呈现全黑。但是,如果我注释掉glActiveTexture(GL_TEXTURE1);,则着色器会再次运行,并且sampler0和sampler1中都会出现相同的纹理。

发生了什么事?有问题的线路glActiveTexture(GL_TEXTURE1);似乎工作得很好,后续的glGetIntegerv(GL_ACTIVE_TEXTURE, &anint)就证明了这一点。它为什么如此可怕地破坏一切?我已经尝试升级我的显示驱动程序。

+0

您是否找到了解决问题的方法?我有完全相同的问题。 – Andrea3000 2012-02-11 09:40:25

+0

是的,标记的解决方案为我工作。 – appas 2012-02-12 07:43:45

回答

24

这是一个基本的GLUT示例(在OS X上编写,根据需要进行调整),生成两个棋盘格纹理,使用两个采样器加载着色器,并通过对每个着色器(一个红色,一个蓝色)和混合进行组合。看看这对你的作品:

#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

+0

好的,这个工程。非常感谢,现在我有一个工作的基础,试图在我自己的程序中找出问题。 – appas 2010-08-30 11:23:54

+1

为什么着色器中的制服叫做“tex0,tex1”,但是当调用“glGetUniformLocation”时,它们被命名为“tex1,tex2”? – Chris 2013-08-21 12:33:30

+1

一个更好的问题可能是:即使其中一个制服的返回位置是“-1”,该如何实现?我已经测试过将统一名称设置为任意字符串,它仍然有效 - 任何人都可以解释这个,请吗? – Chris 2013-08-21 12:46:47

0

听起来像你的glActiveTexture电话不起作用。你确定你正确设置了函数指针吗?

在调用glActiveTexture(GL_TEXTURE1)后,通过调用glGetIntegerv(GL_ACTIVE_TEXTURE, &anint)进行验证。

另外glEnable(GL_TEXTURE_2D)没有用。着色器本身指定要使用的纹理单元以及每个单元的“启用”目标。


编辑补充:

那么,你的新形势是奇特。事实上,你甚至不能显示红色是奇怪的,特别是(为了确定,你是否将alpha设置为1)?

这就是说,你应该恢复GL_TEXTURE0为glActiveTexture你完成设置纹理单元1(即glBindTexture呼叫后)。

+0

也许他将ARB扩展的枚举与核心功能(函数)混合在一起?奇怪的确如此。 – 2010-08-25 23:09:41

+1

感谢您的快速回复。你是对的 - GL_ACTIVE_TEXTURE设置不正确。我现在已经修复了函数指针和值的变化 - 但现在,我所得到的只是黑色。 我已经用我的新情况更新了这个问题。 – appas 2010-08-25 23:10:50

+0

@Mads Elvheim:澄清了最后一句话。 – Bahbar 2010-08-26 06:54:19

2

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

  1. coords应该被分配的4分量gl_TexCoord,例如的st

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

您是否正在检查着色器编译正确的主程序中的任何位置?您可能想通过glGetShaderglGetShaderInfoLog查看GL_COMPILE_STATUS

+0

好吧,我改变了作业,但没有效果。 分号是一个错字,所以我将它从原始邮件中删除。 我已经检查了GL_COMPILE_STATUS,并且着色器在所有情况下都能正确编译和绑定,但实际上只有当我省略'glActiveTexture(GL_TEXTURE1); - 行时才能正常工作,即使我用一个只是用oneliner替换整个东西输出白色。 – appas 2010-08-26 22:02:33

8

比较晚的答复,但对于遇到此问题的任何人 - 我遇到同样的问题,经过短暂的摆弄之后,我意识到拨打glActiveTexture(GL_TEXTURE0)可以解决问题。 如果活动纹理单元未被“重置”为零,看起来似乎有些问题会变得困惑。 这可能是系统相关的行为;我使用Mesa 8.0.4运行64位Archlinux。

+0

这固定了一个奇怪的相关问题,我也有。非常bizarro – 2016-12-04 15:13:20

+0

绝对的现场救星!我浏览了我的代码,解构了代码,直到我在文档和在线搜索到处搜索,并且找不到任何错误。如果可以的话,我会赞成你100,John:^)(win7 64bit GTX780) – yapdog 2017-09-02 17:21:48

10

只是为了帮助其他人可能有兴趣使用多种纹理,并会在寻找答案后的几天感到绝望。我发现,你需要调用

glUseProgram(program); 

GLuint t1Location = glGetUniformLocation(program, "tex1"); 
GLuint t2Location = glGetUniformLocation(program, "tex2"); 

glUniform1i(t1Location, 0); 
glUniform1i(t2Location, 1); 

的顺序为它工作(glUseProgram是示例代码中,我发现99%的最后一个指令在线)。现在对我来说可能只是这种情况,并不会影响地球上的任何其他人,但以防万一我以为我会分享。

+1

没错,手册页上说“glUniform通过调用glUseProgram()对当前状态的一部分进行操作” – 2014-06-14 14:33:27

+0

这对我来说不起作用(在OpenGL 2.0/GLSL 1.2中),但是glGetUniformLocation/glUseProgram/glUniform1i确实 - http://stackoverflow.com/a/25252981/236081 – d3vid 2014-08-11 22:24:11