在Android设备上的片段着色器中使用循环变量进行数组索引

时间:2014-07-22 07:41:47

标签: android opengl-es shader gpuimage fragment-shader

我在Android的GPUImage框架中编写着色器代码。然后我在片段着色器中遇到了数组索引的问题。

根据The OpenGL ES Shading Language的附录,在顶点着色器中,统一数组可以被任何整数索引,并且变量数组可以通过constant-index-expression索引。在片段着色器中,两个(统一/变化)数组只能通过常量索引表达式进行索引。在constant-index-expression的定义下,for循环索引应该能够用作数组索引。

然而,当我在片段着色器中使用循环索引作为数组索引时出现问题。没有编译错误,并且可以运行着色器代码,但似乎程序在循环的每一轮中将所有索引值都视为0。

这是我的片段着色器代码:

uniform sampler2D inputImageTexture;
uniform highp float sample_weights[9]; // passed by glUniform1fv
varying highp vec2 texture_coordinate;
varying highp vec2 sample_coordinates[9]; // computed in the vertex shader
...
void main()
{
    lowp vec3 sum = vec3(0.0);
    lowp vec4 fragment_color = texture2D(inputImageTexture, texture_coordinate);
    for (int i = 0; i < 9; i++)
    {
        sum += texture2D(inputImageTexture, sample_coordinates[i]).rgb * sample_weights[i];
    }
    gl_FragColor = vec4(sum, fragment_color.a);
}

如果我展开循环并访问数组的[0]到[8],结果将是正确的。 但是,使用循环索引时,结果是错误的,并且与运行

相同
sum += texture2D(inputImageTexture, sample_coordinates[0]).rgb * sample_weights[0];

9次,并且在此过程中没有报告编译错误。

我只测试过一台设备,即Android版4.3的Nexus 7。 GPUImage框架使用android.opengl.GLES20,但不使用GLES30。

这是对Android设备或OpenGL ES 2.0中着色器代码的额外限制,还是与设备相关的问题?

更新: 在测试了更多Android设备(4.1~4.4)之后,似乎只有Nexus 7设备才会出现此问题。其他设备上的结果是正确的。这很奇怪。这是个别设备上的实施问题吗?

1 个答案:

答案 0 :(得分:3)

这是一个鲜为人知的事实,但在循环中的纹理查找是GLSL中未定义的事情。特别是小句子:&#34;衍生物在非统一控制流程中未定义&#34;,请参阅GLSL ES规范的section 8.9。并参见section 3.9.2以找出非均匀控制流程。这在其他设备上运行的事实是偶然的。

你唯一的选择可能是不幸地解开循环。