1

在我在 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;
}
4

1 回答 1

1

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

编辑:实际上,我不久前就找到了具体原因——我一直在使用一些 Apple 的 GLKit 示例项目,它将着色器属性绑定到一个枚举,该枚举位于我使用的示例中的 @implementation 之外View Controller,这意味着它的范围在类的特定实例之外。有这个问题的类实际上有两个着色器,当第二个被编译时它删除了以前的绑定。那么真正的谜团是为什么我给出的第一个解决方案首先起作用......

于 2013-08-18T20:55:26.370 回答