更新:神秘解决......有点!
我使用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返回的...任何想法? :(
答案 0 :(得分:1)
这与版本声明或着色器中的精确声明有关。
以前,我只是
#version 120
...因为这个着色器是为桌面GL编写的。当我尝试在旧设备上进行测试时,着色器编译器抱怨版本120不受支持,因此我被迫将其更改为
#version 100
precision mediump float;
通过此更改,现在可以在两个设备上将变量正确报告为整数。我相信这是在Nexus 5上使用120版本时的驱动程序错误。无论如何,这是我最好的猜测!