我使用OpenGL ES 2着色器重新实现了Apple的GLImageProcessing。效果很完美,但Sharpness滤镜的性能不是很好 - 它只能以20 FPS运行。
着色器代码很简单:
基本上,Pass 2中的纹理混合是缓慢的原因,因为Pass 0和Pass 1只进行一次而且不会导致性能不佳。
如何改善表现?
顶点着色器:
attribute vec4 a_position;
attribute vec2 a_texCoord;
varying highp vec2 v_texCoord;
varying highp vec2 v_texCoord1;
varying highp vec2 v_texCoord2;
varying highp vec2 v_texCoord1_;
varying highp vec2 v_texCoord2_;
uniform mat4 u_modelViewProjectionMatrix;
uniform lowp int u_pass;
const highp float blurSizeH = 1.0 / 320.0;
const highp float blurSizeV = 1.0 / 480.0;
void main()
{
v_texCoord = a_texCoord;
if (u_pass == 0) {
v_texCoord1 = a_texCoord + vec2(1.3846153846 * blurSizeH, 0.0);
v_texCoord1_ = a_texCoord - vec2(1.3846153846 * blurSizeH, 0.0);
v_texCoord2 = a_texCoord + vec2(3.2307692308 * blurSizeH, 0.0);
v_texCoord2_ = a_texCoord - vec2(3.2307692308 * blurSizeH, 0.0);
} else if (u_pass == 1) {
v_texCoord1 = a_texCoord + vec2(0.0, 1.3846153846 * blurSizeV);
v_texCoord1_ = a_texCoord - vec2(0.0, 1.3846153846 * blurSizeV);
v_texCoord2 = a_texCoord + vec2(0.0, 3.2307692308 * blurSizeV);
v_texCoord2_ = a_texCoord - vec2(0.0, 3.2307692308 * blurSizeV);
}
gl_Position = u_modelViewProjectionMatrix * a_position;
}
片段着色器:
varying highp vec2 v_texCoord;
varying highp vec2 v_texCoord1;
varying highp vec2 v_texCoord2;
varying highp vec2 v_texCoord1_;
varying highp vec2 v_texCoord2_;
uniform lowp int u_pass;
uniform sampler2D u_texture;
uniform sampler2D u_degenTexture;
uniform mediump mat4 u_filterMat;
void main()
{
if (u_pass == 0) {
gl_FragColor = texture2D(u_texture, v_texCoord) * 0.2270270270;
gl_FragColor += texture2D(u_texture, v_texCoord1) * 0.3162162162;
gl_FragColor += texture2D(u_texture, v_texCoord1_) * 0.3162162162;
gl_FragColor += texture2D(u_texture, v_texCoord2) * 0.0702702703;
gl_FragColor += texture2D(u_texture, v_texCoord2_) * 0.0702702703;
} else if (u_pass == 1) {
gl_FragColor = texture2D(u_degenTexture, v_texCoord) * 0.2270270270;
gl_FragColor += texture2D(u_degenTexture, v_texCoord1) * 0.3162162162;
gl_FragColor += texture2D(u_degenTexture, v_texCoord1_) * 0.3162162162;
gl_FragColor += texture2D(u_degenTexture, v_texCoord2) * 0.0702702703;
gl_FragColor += texture2D(u_degenTexture, v_texCoord2_) * 0.0702702703;
} else {
gl_FragColor = u_filterMat * texture2D(u_texture, v_texCoord) + (mat4(1.0) - u_filterMat) * texture2D(u_degenTexture, v_texCoord);
}
}
答案 0 :(得分:1)
在继续这个之前,我建议你看看我的开源GPUImage项目吗?我在那里有几个手动优化的锐化效果,包括你在这里尝试的非锐化面具。我也很容易吸引图像和视频资源。
对于您的具体问题,有几个原因导致着色器运行速度低于预期。首先,您在片段着色器中使用分支。这会杀死iOS设备上的性能,如果可能的话应该避免。如果您确实需要为不同的传递设置不同的条件,请将它们拆分为单独的着色器程序,并根据需要交换程序,而不是使用统一控制流程。
我也不确定反复写入gl_FragColor是你能在这里做的最快的事情。我将使用lowp或mediump中间颜色变量,将高斯分量添加到其中,然后在完成时将最终结果写入gl_FragColor。
我确实看到你已经将采样偏移计算移动到顶点着色器,然后将这些偏移传递到片段着色器,这是人们通常会错过的好东西。一旦你实现了上面的调整(或者试着让我的框架看看我是如何处理这个),你应该从过滤中获得更好的结果。
答案 1 :(得分:1)
事实证明这很简单。性能不佳的原因是矩阵向量乘法:
varying highp vec2 v_texCoord;
uniform sampler2D u_texture;
uniform sampler2D u_degenTexture;
uniform lowp float u_filterValue;
void main()
{
gl_FragColor = u_filterMat * texture2D(u_texture, v_texCoord) + (mat4(1.0) - u_filterMat) * texture2D(u_degenTexture, v_texCoord);
}
我最初使用矩阵编写代码,这样我的所有过滤器都可以共享相同的颜色混合代码。现在我学到了这一课,我只是回过头来编写特定于过滤器的代码并尽可能地使用标量操作:
varying highp vec2 v_texCoord;
uniform sampler2D u_texture;
uniform sampler2D u_degenTexture;
uniform lowp float u_filterValue;
void main()
{
gl_FragColor = u_filterValue * texture2D(u_texture, v_texCoord) + (1.0 - u_filterValue) * texture2D(u_degenTexture, v_texCoord);
}
现在它真棒60 fps!
从来没有想过这是一个如此天真的问题,但确实如此。