2010-08-25 49 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