Try switching every arrays to vec4:
uniform vec4 t[2];
uniform vec4 kernel[16];
And use t[i].x
and kernel[i].xyz
in the shader.
Upload them as vec4 on the CPU side as well (don't forget padding with w
)
struct Vector{ float x,y,z,w; }
float threshold[2][4] = { {0.5f}, {0.25f} };
Vector *kernel = new Vector[_kernel_size]; // _kernel_size==16
// fill kernel
glUniform4fv(glGetUniformLocation(_program, "t"), 2, threshold);
glUniform4fv(glGetUniformLocation(_program, "kernel"), _kernel_size, (const GLfloat*)kernel);
It's possible the GPU and drivers only properly supports arrays of vec4 due to a hardware limitation.
Alternatively, you can use t.x
and t.y
as the two thresholds in the shader:
uniform vec4 t;
CPU side:
float threshold[4] = { 0.5f, 0.25f };
glUniform4fv(glGetUniformLocation(_program, "t"), 1, threshold);
If that doesn't work try uploading each uniform one by one.
glUniform4fv(glGetUniformLocation(_program, "kernel[0]"), 1, kernel+0);
glUniform4fv(glGetUniformLocation(_program, "kernel[1]"), 1, kernel+1);
...
(for-loop left out for brevity)
Mobile GPUs (ie: cell phones) tend to be scalar-based (not vector) and can access floats, vec2s and vec4s just fine. Avoid vec3 uniforms but using them as temporaries in the shader code is fine and will be faster. Use lower precisions / fixed points when possible on Mobile.
Desktop GPUs vary. Some are vector4-only internally and the driver has to put floats into vec4s. Some can access scalar uniforms at any address with a slight performance penalty.
If you have multiple arrays of floats it's a good idea to interleave them if you can
For example:
uniform vec4 table[8];
table[i].x // hue shift table
table[i].y // blur factor table
table[i].z // de-saturation factor table
// etc
If you can, invest a few bucks in getting test computers with GPUs from other manufacturers to make sure your code and shaders work on most, test regularly.
They all have quirks, some more than others.
struct Vector{ float x,y,z; }
seems wrong to me. Trystruct Vector {float x; float y; float z;}
\$\endgroup\$value
? Should it bekernel
what you want to pass to the shader? \$\endgroup\$kernel
. I made mistake because I have glUniforms wrapped in functions and I copy, pase and edit this fragment :) I'll try with struct but I tried cast mykernel
toconst float*
and then in0.._kernel_size*3
loop I iterated over this array and values were good. \$\endgroup\$