在 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 对所有片段都相同的值进行插值,这是一个完全无用的操作。
更好的解决方案:
- 在片段着色器中使用制服来存储你的内核(这样你也可以从你的应用程序代码中改变它......)
- 将你的内核存储在你在片段着色器中采样的纹理中,在这种情况下确保纹理使用最近的过滤(同样,你可以从应用程序代码更改纹理。只要你需要......)
(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 对所有片段都相同的值进行插值,这是一个完全无用的操作。
更好的解决方案:
- 在片段着色器中使用制服来存储你的内核(这样你也可以从你的应用程序代码中改变它......)
- 将你的内核存储在你在片段着色器中采样的纹理中,在这种情况下确保纹理使用最近的过滤(同样,你可以从应用程序代码更改纹理。只要你需要......)