我用OpenGL ES 2着色器重新实现了Apple的GLImageProcessing。效果是完美的,但是“锐度”滤镜的性能却不如它—仅以20 FPS运行。

着色器代码很简单:

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

  • 基本上,第2遍中的纹理混合是速度较慢的原因,因为第0遍和第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);
        }
    }
    

    最佳答案

    在继续之前,我是否建议您看一下我的开源GPUImage项目?我在那里有几个手动优化的锐化效果,包括您在此处尝试的不清晰蒙版。我还使引入图像和视频源变得相当容易。

    对于您的特定问题,着色器的运行速度比预期的慢有两个原因。首先是您正在片段着色器中使用分支。这会破坏iOS设备上的性能,应尽可能避免使用。如果确实需要针对不同的传递使用不同的条件,请将它们分成单独的着色器程序,然后根据需要交换出程序,而不要使用统一的控制流。

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

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

    07-25 22:36
    查看更多