在 glsl v100 中将大数组从顶点传递到片段着色器

Passing a large array from vertex to fragment shader in glsl v100

(OpenGL ES 2.0) (glsl v100)

我正在尝试将一个大内核传递给片段着色器以进行卷积运算。我首先动态创建着色器并对所有内核颜色进行硬编码,但出于某种原因,如果我读取索引 31 之后的数组,着色器不会编译并且不会给出错误。下面是我在试图找出问题出在哪里时得到的一些代码。

顶点着色器

attribute vec4 position;
attribute vec4 inputTextureCoordinate;
varying float kernelColors[33];

void main()
{
    gl_Position = position;

    kernelColors[0] = 0.000000;
    kernelColors[1] = 1.000000;
    kernelColors[2] = 1.000000;
    kernelColors[3] = 1.000000;
    kernelColors[4] = 1.000000;
    kernelColors[5] = 1.000000;
    kernelColors[6] = 1.000000;
    kernelColors[7] = 1.000000;
    kernelColors[8] = 1.000000;
    kernelColors[9] = 1.000000;
    kernelColors[10] = 1.000000;
    kernelColors[11] = 1.000000;
    kernelColors[12] = 1.000000;
    kernelColors[13] = 1.000000;
    kernelColors[14] = 1.000000;
    kernelColors[15] = 1.000000;
    kernelColors[16] = 1.000000;
    kernelColors[17] = 1.000000;
    kernelColors[18] = 1.000000;
    kernelColors[19] = 1.000000;
    kernelColors[20] = 1.000000;
    kernelColors[21] = 1.000000;
    kernelColors[22] = 1.000000;
    kernelColors[23] = 1.000000;
    kernelColors[24] = 1.000000;
    kernelColors[25] = 1.000000;
    kernelColors[26] = 1.000000;
    kernelColors[27] = 1.000000;
    kernelColors[28] = 1.000000;
    kernelColors[29] = 1.000000;
    kernelColors[30] = 1.000000;
    kernelColors[31] = 1.000000;
    kernelColors[32] = 1.000000;
}

片段着色器

precision highp float;
uniform sampler2D inputImageTexture;
varying float kernelColors[33];

void main()
{

    kernelColors[0];
    kernelColors[1];
    kernelColors[2];
    kernelColors[3];
    kernelColors[4];
    kernelColors[5];
    kernelColors[6];
    kernelColors[7];
    kernelColors[8];
    kernelColors[9];
    kernelColors[10];
    kernelColors[11];
    kernelColors[12];
    kernelColors[13];
    kernelColors[14];
    kernelColors[15];
    kernelColors[16];
    kernelColors[17];
    kernelColors[18];
    kernelColors[19];
    kernelColors[20];
    kernelColors[21];
    kernelColors[22];
    kernelColors[23];
    kernelColors[24];
    kernelColors[25];
    kernelColors[26];
    kernelColors[27];
    kernelColors[28];
    kernelColors[29];
    kernelColors[30];
    kernelColors[31];

    kernelColors[32]; //if i comment this line out it works


    gl_FragColor = vec4(vec3(.3,.5,.1), 1.0);



}

可能有更好的方法来做到这一点,但我仍然想知道为什么上面的代码无法编译。

关于其他方法 - 'flat' 限定符在 glsl 100 中不可用,所以我不能应用它,如果它甚至 change/optimize 任何东西。另外,如果我将内核数据作为纹理加载,如果我没有动态索引,我该如何迭代像素?

我需要将每个像素与内核进行卷积,内核不会在帧与帧之间发生变化,但在某些情况下我可能需要将其换成另一个内核。

根据您 运行 使用的设备(搜索 MAX_VARYING_VECTORS 和 OpenGLES),您可以使用的变量数量有限制,如果超过它,着色器将无法编译。

但是使用 varyings 来存储每个像素都相同的内核完全是一种资源浪费。请记住,在顶点着色器中为顶点设置了变量,然后 GPU 为每个像素在它们之间进行插值,所以在这里你告诉 GPU 对所有片段都相同的值进行插值,这是一个完全无用的操作。

更好的解决方案:

  • 在片段着色器中使用制服来存储你的内核(这样你也可以从你的应用程序代码中改变它......)
  • 将你的内核存储在你在片段着色器中采样的纹理中,在这种情况下确保纹理使用最近的过滤(同样,你可以从应用程序代码更改纹理。只要你需要......)