2013-08-18 174 views
1

在我運行在iPad模擬器上的iOS項目中,我有3個着色器程序,每個着色器程序使用類似但不相同的屬性和制服集。前兩種着色器編譯和工作完美,在編譯或繪圖過程中任何時候都不會出現gl錯誤。我現在需要添加第三個着色器,並且這引起了一個問題:現在,其他着色器都不繪製任何東西,並且當我嘗試使用glUniform傳遞制服時,glGetError返回1282(GL_INVALID_OPERATION)。 glGetError在glUniform被調用之前返回0行。編譯GLSL着色器打破其他着色器

我相信在我嘗試調用glUniform之前將程序設置爲正確的程序,因爲當我在傳遞制服之前使用GL_CURRENT_PROGRAM調用glGetIntegerv時,它匹配我嘗試使用的程序的gl名稱(I調用glUseProgram與我想要在glUniform調用問題的方法開始時使用的程序)。 glGetError在編譯問題着色器之前和之後返回0。編輯代碼從Apple的示例項目中略有修改,我沒有看到任何內容會影響其他着色器的狀態。

- (BOOL)loadGLProgramWithVertexShader: (NSString*) vertexShaderName fragmentShader: (NSString*) fragementShaderName 
{ 
GLuint vertShader, normFragShader; 
NSString *vertShaderPathname, *normFragShaderPathName; 

// Create shader program. 
shaderProgram = glCreateProgram(); 

// Create and compile vertex shader. 
vertShaderPathname = [[NSBundle mainBundle] pathForResource: vertexShaderName ofType:@"vsh"]; 
if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { 
    NSLog(@"Failed to compile vertex shader"); 
    return NO; 
} 


// Create and compile normal mapping fragment shader. 
normFragShaderPathName = [[NSBundle mainBundle] pathForResource: fragementShaderName ofType:@"fsh"]; 
if (![self compileShader:&normFragShader type:GL_FRAGMENT_SHADER file:normFragShaderPathName]) { 
    NSLog(@"Failed to compile fragment shader"); 
    return NO; 
} 

// Attach vertex shader to program. 
glAttachShader(shaderProgram, vertShader); 

// Attach fragment shader to program. 
glAttachShader(shaderProgram, normFragShader); 

// Bind attribute locations. 
// This needs to be done prior to linking. 
glBindAttribLocation(shaderProgram, ATTRIB_VERTEX, "position"); 
glBindAttribLocation(shaderProgram, ATTRIB_TEXTURECOORD, "texCoord"); 

// Link program. 
if (![self linkProgram:shaderProgram]) { 
    NSLog(@"Failed to link program: %d", shaderProgram); 

    if (vertShader) { 
     glDeleteShader(vertShader); 
     vertShader = 0; 
    } 

    if (normFragShader) { 
     glDeleteShader(normFragShader); 
     normFragShader = 0; 
    } 
    if (shaderProgram) { 
     glDeleteProgram(shaderProgram); 
     shaderProgram = 0; 
    } 

    return NO; 
} 

// Get uniform locations. 
uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(shaderProgram, "modelViewProjectionMatrix"); 
uniforms[UNIFORM_TEXTURE] = glGetUniformLocation(shaderProgram, "texture"); 


// Release vertex and fragment shaders. 
if (vertShader) { 
    glDetachShader(shaderProgram, vertShader); 
    glDeleteShader(vertShader); 
} 

if (normFragShader) { 
    glDetachShader(shaderProgram, normFragShader); 
    glDeleteShader(normFragShader); 
} 

return YES; 
} 

回答

1

我找到了答案。在我的第三個着色器中,我有一個名爲「紋理」的sa​​mpler2D。在着色器中更改此名稱並調用glGetUniformLocation可解決問題。我不明白爲什麼,因爲「紋理」不是GLSL中的保留字,並且在任何其他制服中沒有其他用法(有一個「texcoord」屬性,但我懷疑這導致了問題) ,但它的工作。

編輯︰我實際上找到了這個前一個具體的原因 - 我一直在使用Apple的GLKit示例項目,它將着色器屬性綁定到一個枚舉,這是在我使用的示例中放置View Controller的實現,這意味着它的作用域在類的特定實例之外。有這個問題的類實際上有兩個着色器,當第二個被編譯時,它刪除了以前的綁定。那真正的奧祕就是爲什麼我給的第一個解決方案在第一個地方工作...