1

我使用 OpenGL ES 2 着色器重新实现了 Apple 的GLImageProcessing 。效果是完美的,但清晰度滤镜的性能并不好——它只能以 20 FPS 运行。

着色器代码很简单:

  1. 为水平模糊传递 0。
  2. 通过 1 进行垂直模糊。
  3. 通过 2 将模糊纹理与原始纹理混合。

基本上,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);
    }
}
4

2 回答 2

1

在你继续这个之前,我可以建议你看看我的开源GPUImage项目吗?我有几个手动优化的锐化效果,包括你在这里尝试的不锐化蒙版。我还使提取图像和视频源变得相当容易。

对于您的具体问题,您的着色器运行速度比预期慢有几个原因。首先是您在片段着色器中使用分支。这会降低 iOS 设备的性能,应尽可能避免。如果您确实需要为不同的通道设置不同的条件,请将它们拆分为单独的着色器程序并根据需要交换程序,而不是使用统一的控制流。

我也不确定重复写入 gl_FragColor 是你可以在这里做的最快的事情。我会使用 lowp 或 mediump 中间颜色变量,将您的高斯分量添加到其中,然后在完成后将最终结果写入 gl_FragColor。

我确实看到您已将采样偏移计算移至顶点着色器,然后将这些偏移传递到片段着色器,这是人们通常会错过的一件好事。一旦你实施了上述调整(或尝试我的框架,看看我是如何处理的),你应该从你的过滤中得到更好的结果。

于 2013-04-06T16:04:42.567 回答
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!

从来没有想过这是一个如此幼稚的问题,但确实如此。

于 2013-05-22T22:52:37.287 回答