编译GLSL着色器会破坏其他着色器

时间:2013-08-18 17:05:02

标签: ios ipad opengl-es-2.0 glsles

在我在iPad模拟器上运行的iOS项目中,我有3个着色器程序,每个程序使用相似但不完全相同的属性和制服集。这两个着色器中的前两个完美地编译和协同工作,在编译或绘图过程中的任何一点都没有gl错误。我现在需要添加第三个着色器,这引起了一个问题:现在,两个其他着色器都没有绘制任何东西,当我尝试使用glUniform传递制服时,glGetError返回1282(GL_INVALID_OPERATION)。 glGetError在调用glUniform之前返回0行。

我相信我在尝试调用glUniform之前将程序设置为正确的程序,因为当我在传递制服之前用GL_CURRENT_PROGRAM调用glGetIntegerv时,它匹配我尝试使用的程序的gl名称(我调用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 个答案:

答案 0 :(得分:1)

我找到了答案。在我的第三个着色器中,我有一个名为“texture”的sampler2D。在Shaders中更改此名称并调用glGetUniformLocation修复了问题。我不明白为什么,因为“纹理”不是GLSL中的保留字,并且在任何其他制服中没有其他用词(有“texcoord”属性,但我怀疑这导致了问题) ,但它奏效了。

编辑:我实际上找到了这个问题的具体原因 - 我曾经使用过一些Apple的GLKit示例项目,该项目将着色器属性绑定到我使用的样本中的枚举。 View Controller的实现,意味着它的范围超出了类的特定实例。有这个问题的类实际上有两个着色器,当第二个被编译时,它擦除了以前的绑定。真正的谜团就是为什么我给出的第一个解决方案首先起作用了......