写入gl_FragColor会导致glUseProgram抛出GL_INVALID_OPERATION

时间:2013-03-17 02:12:38

标签: opengl-es glsl glsles

我正在尝试在GLSL ES 2.0中编写一个模糊过滤器,并且我在行分配gl_FragColor时遇到错误。我无法弄明白为什么

#extension GL_OES_EGL_image_external : require
precision mediump float;
varying vec2 textureCoordinate;
uniform samplerExternalOES s_texture;
void main() {
  float gaus[25] = float[25](0.01739, 0.03478, 0.04347, 0.03478, 0.01739,
                             0.03478, 0.07282, 0.10434, 0.07282, 0.03478,
                             0.04347, 0.10434, 0.13043, 0.10434, 0.04347,
                             0.03478, 0.07282, 0.10434, 0.07282, 0.03478,
                             0.01739, 0.03478, 0.04347, 0.03478, 0.01739);
  float offset[5] = float[5](-2.0, -1.0, 0.0, 1.0, 2.0);
  vec4 outSum = vec4(0.0);
  int rowi = 0;
  for(int i = 0; i < 5; i++){
    vec4 inSum = vec4(0.0);
    for(int j = 0; j < 5; j++){
      inSum += texture2D(s_texture, textureCoordinate + vec2(offset[i], offset[j]))*gaus[j*5+i];
    }
    outSum += inSum*gaus[rowi+i];
    rowi += 3;
  }
  gl_FragColor = outSum;
}

gl_FragColor的分配导致glUseProgram的调用错误GL_INVALID_OPERATION。我已经尝试过没有它,它编译并运行没有错误。我希望有人能指出我尚未看过的方向,至少因为我看不出任何不合理的原因。

编辑:我解决了这个问题。最好我可以告诉android上的GLSL-ES不允许使用非常量变量索引数组。 GLSE-ES 2.0规范第97页10.25声明它并非所有实现都直接支持,并且在页109中它声明循环索引可以被认为是常量表达式但不是必须的。我推出了我的循环,现在连接正常。

感谢所有回复的人,由于您的洞察力,我能够缩小范围。

3 个答案:

答案 0 :(得分:2)

如果删除这些行会怎样?

uniform float gaus[25];
uniform float offset[5];

gaus和offset不是制服。它们在main()中被赋予常量值。而且我认为你不应该声明与制服名称相同的变量。

我记得在编译着色器时,编译器非常擅长从着色器中剥离不必要的代码。当你遗漏这条线时

gl_FragColor = outSum; 

或指定

texture2D(s_texture, textureCoordinate) 

到gl_FragColor,gaus和offset不用于计算gl_FragColor的最终值,因此它们可能被剥离并且不会发生变量命名冲突。将outSum指定给gl_FragColor时,gaus和offset用于计算outSum,因此它们不会被剥离,并且会发生命名冲突,从而导致错误。

答案 1 :(得分:2)

如果符合以下情况,

glUseProgram只能抛出GL_INVALID_OPERATION

  1. 该程序不是有效的程序对象。
  2. 该程序的最后一个链接操作未成功。
  3. 显然,您对此变量的写入会导致您未检测到的着色器编译或链接错误。因此,开始捕获编译器/链接器错误而不是忽略它们。

答案 2 :(得分:0)

这更像是对尼科尔答案的延伸。

我遇到了同样的问题,结果发现该程序的链接失败了。不幸的是,在glGetError之后glLinkProgram没有返回错误,我最终没有收到它。我添加了以下内容,帮助我在链接后记录错误,并且非常有用。

GLint logLength;
glGetProgramiv( program_id, GL_INFO_LOG_LENGTH, &logLength );
if ( logLength > 0 )
{
    char* log = new char[ logLength + 1 ];
    log[ logLength ] = '\0';
    glGetProgramInfoLog( program_id, logLength, &logLength, log );
    Dbg_Printf( "OpenGL Program Link Log:\n%s\n", log );
    delete[] log;
}

BTW,就我而言,我超过了顶点着色器中支持的属性数量。