来自glUniform1i的无法解释的GL_INVALID_OPERATION(OpenGL认为int是一个浮点?)

时间:2014-10-02 15:49:50

标签: android c++ opengl-es

更新:神秘解决......有点!

我使用glGetActiveUniform来研究GLSL认为我的制服是什么类型的变量。

这是输出:

I/KGLT    (21149): 2005266104: UNIFORM active_texture_count with size 1 and type 5126 (//kglt/kglt/gpu_program.cpp:368)

5126型是GL_FLOAT!?!确实使用glUniform1f解决了这个问题,但为什么呢?当着色器中的定义肯定是int?

以下原始问题

我将我的游戏引擎移植到Android。在桌面上我使用OpenGL 3.x和GLSL 1.2,在Android上我使用的是GLES 2.0。

由于某些原因,在我的Android手机上,我从glUniform1i收到GL_INVALID_OPERATION错误,但我无法弄清楚原因是什么。

我添加了一些日志记录来显示问题:

E/KGLT    (28500): 2006330776: Attempting to set uniform value of 0 at location 0 for name active_texture_count (//kglt/kglt/gpu_program.cpp:50)
W/Adreno-ES20(28500): <__load_uniform_int:351>: GL_INVALID_OPERATION
E/KGLT    (28500): 2006330776: An OpenGL error occurred: void kglt::UniformManager::set_int(const unicode &, const int32_t) - GL_INVALID_OPERATION (//kglt/kglt/utils/gl_error.cpp:41)

您会注意到Adreno-ES20在我之前记录问题,也就在我调用glUniform1i之前,我记录了我设置的值,从glGetUniformLocation返回的位置,以及统一名称(不是那个相关的)真)。我已经验证了GL调用是在主线程中进行的,所以在这里应该没有线程问题。

根据文档,glUniformX可以在以下情况下引发INVALID_OPERATION,我将内联评论:

GL_INVALID_OPERATION is generated if there is no current program object.

我已经检查过,肯定有一个程序对象,它就是我期待它的那个。选中glGetIntegerv(GL_CURRENT_PROGRAM, ...)

GL_INVALID_OPERATION is generated if the size of the uniform variable declared in the shader does not match the size indicated by the glUniform command.

GLSL中的统一声明是:

    uniform int active_texture_count;

对我来说绝对看起来像一个整数,所以使用glUniform1i是对的吗?这是我最怀疑的,这里是否涉及某种包装问题?

GL_INVALID_OPERATION is generated if one of the integer variants of this function is used to load a uniform variable of type float, vec2, vec3, vec4, or an array of these, or if one of the floating-point variants of this function is used to load a uniform variable of type int, ivec2, ivec3, or ivec4, or an array of these.

见上文,我不认为我这样做。我肯定使用glUniform1i,值肯定是一个整数,并且着色器变量明确定义为整数。

GL_INVALID_OPERATION is generated if location is an invalid uniform location for the current program object and location is not equal to -1.

我在调用glUniform1i之前立即调用glGetUniformLocation,具有相同的绑定程序ID。它返回零,这是一个有效的位置(因为-1是错误值)。有什么方法可以验证位置是否指的是我认为它的变量名称?

GL_INVALID_OPERATION is generated if count is greater than 1 and the indicated uniform variable is not an array variable.

count不是glUniform的1i变体的参数,因此不适用。

GL_INVALID_OPERATION is generated if a sampler is loaded using a command other than glUniform1i and glUniform1iv.

我没有设置采样器值,即使我是,我仍然使用正确的变体。

我在这里完全失去了,我已经盯着这段代码好几个小时了,谷歌周围找不到任何可能表明问题所在的东西。我也不确定我的下一步应该是调试它。

如果它有用,那么这里是整个片段着色器:

    uniform sampler2D textures[2];
    uniform vec4 global_ambient;
    uniform int active_texture_count;
    uniform vec4 material_ambient;

    varying vec2 frag_texcoord0;
    varying vec2 frag_texcoord1;
    varying vec4 frag_diffuse;

    void main() {
        if(active_texture_count == 0) {
            gl_FragColor = frag_diffuse * global_ambient * material_ambient;
        } else {
            vec4 t1 = texture2D(textures[0], frag_texcoord0.st);
            vec4 t2 = texture2D(textures[1], frag_texcoord1.st);
            if(active_texture_count < 2) {
                t2 = vec4(1.0, 1.0, 1.0, 0.0);
            }
            gl_FragColor = (((1.0 - t2.a) * t1) + (t2.a * t2)) * frag_diffuse * global_ambient * material_ambient;
        }
    }

编辑:我已将代码更新为非常明确,因此这是当前代码

if(glGetError() != GL_NO_ERROR) {
    L_DEBUG("There was an error before setting the uniform");
}
glUseProgram(program_.program_object_);

if(glGetError() != GL_NO_ERROR) {
    L_DEBUG("There was an error after using the program");
}

GLint loc = glGetUniformLocation(program_.program_object_, name.c_str());//locate(uniform_name);

if(glGetError() != GL_NO_ERROR) {
    L_DEBUG("There was an error after getting the uniform location");
}

L_DEBUG(_u("Setting value {0} for uniform at location {1}").format(value, loc));
glUniform1i(loc, value);

if(glGetError() != GL_NO_ERROR) {
    L_DEBUG("There was an error after setting the uniform");
} else {
    L_DEBUG("Uniform set sucessfully");
}

以下是日志记录输出

I/KGLT    (12770): 2005266248: Setting value 0 for uniform at location 0 (//kglt/kglt/gpu_program.cpp:64)
W/Adreno-ES20(12770): <__load_uniform_int:351>: GL_INVALID_OPERATION
I/KGLT    (12770): 2005266248: There was an error after setting the uniform (//kglt/kglt/gpu_program.cpp:68)

正如您所看到的,之前没有错误,程序处于活动状态,该位置是直接从GL返回的...任何想法? :(

1 个答案:

答案 0 :(得分:1)

这与版本声明或着色器中的精确声明有关。

以前,我只是

#version 120

...因为这个着色器是为桌面GL编写的。当我尝试在旧设备上进行测试时,着色器编译器抱怨版本120不受支持,因此我被迫将其更改为

#version 100
precision mediump float;

通过此更改,现在可以在两个设备上将变量正确报告为整数。我相信这是在Nexus 5上使用120版本时的驱动程序错误。无论如何,这是我最好的猜测!