ios - 使用 OpenGL ES 2 着色器重新实现的 GLImageProcessing 的性能问题

标签 ios opengl-es fragment-shader

我重新实现了 Apple 的 GLImageProcessing使用 OpenGL ES 2 着色器。效果是完美的,但锐度过滤器的性能不是很好 — 它仅以 20 FPS 的速度运行。

着色器代码很简单:

  1. 为水平模糊传递 0。
  2. 传递 1 以实现垂直模糊。
  3. 第 2 步将模糊纹理与原始纹理混合。

基本上, channel 2 中的纹理混合是导致速度缓慢的原因,因为 channel 0 和 channel 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 设备的性能,应尽可能避免。如果您确实需要为不同的 channel 设置不同的条件,请将它们分成单独的着色器程序并根据需要交换程序,而不是使用统一的控制流。

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

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

关于ios - 使用 OpenGL ES 2 着色器重新实现的 GLImageProcessing 的性能问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15752679/

相关文章:

c++ - 为什么我的 OpenGL 自定义着色器给我这个错误?

android - vec4 add fragment 着色器中的 GLSL 性能问题

ios - UILocalNotification 在应用程序启动时被重复调用

ios - 当我点击 MapKit 中的图钉时如何执行操作? ios9, swift 2

java - OpenGL ES 纹理无法绘制

类似于 iPhone 的 Android OpenGL 混合

javascript - Math.random() 未声明的标识符

opengl-es - 使用片段着色器在二维多边形上绘制边框

ios - iOS 上的 PhoneGap 应用程序感觉原生的 UI

ios - 尝试设置 Firebase 推送通知时出现错误