Search code examples
opengl-es-2.0glsles

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


(OpenGL ES 2.0) (glsl v100)

I am trying to pass a large kernel to the fragment shader for a convolution operation. I started by creating the shader dynamically and hardcoding all the kernel colors, but for some reason if I read the array past index 31 the shader does not compile and no error is given. Below is some code i ended up with while trying to figure where the problem is.

vertex shader

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;
}

fragment shader

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);



}

There is probably a better way to do this, but i still would like to know why the code above does not compile.

Regarding other methods - the 'flat' qualifier is not available in glsl 100, so I can't apply that if that would even change/optimize anything. Also if I load in the kernel data as a texture how can I iterate over the pixels if I can't have a dynamic index?

I need to convolve each pixel with the kernel, the kernel does not change from frame to frame but I may need to swap it out for another kernel in some cases.


Solution

  • There is a limit on the amount of varying you can use depending on the device you run on (search about MAX_VARYING_VECTORS and OpenGLES), if you exceed it shader will not compile.

    But using varyings to store a kernel which is the same for each pixel is a complete waste of resources. Remember that varyings are set for vertices in vertex shader and then GPU interpolates between them for each pixel, so here you are telling the GPU to interpolate values which are the same for all fragments, this is a totally useless operation.

    Better solutions :

    • Use uniforms in the fragment shader to store your kernel (like that you can also change it from your app code ...)
    • Store your kernel in a texture which you sample in the fragment shader, in this case make sure that the texture uses nearest filtering (same, you can change the texture from app code. whenever you need...)