1

Apple のGLImageProcessingを OpenGL ES 2 シェーダーで再実装しました。効果は完璧ですが、シャープネス フィルターのパフォーマンスはそれほど良くありません。20 FPS でしか動作しません。

シェーダー コードは単純です。

  1. 水平方向のぼかしには 0 を渡します。
  2. 垂直方向のぼかしには 1 を渡します。
  3. 2 を渡して、ブラー テクスチャを元のテクスチャとミックスします。

基本的に、パス 0 とパス 1 は 1 回だけ実行され、パフォーマンスの低下には寄与しないため、パス 2 のテクスチャ ミックスが速度低下の原因です。

どうすればパフォーマンスを向上させることができますか?

頂点シェーダー:

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プロジェクトを見ていただけますか? ここで試みているアンシャープ マスクを含め、手動で最適化されたシャープ効果がいくつかあります。また、画像や動画のソースをかなり簡単に取り込むこともできます。

特定の質問に対して、シェーダーの実行が予想よりも遅い理由がいくつかあります。1 つ目は、フラグメント シェーダー内で分岐を使用していることです。これにより、iOS デバイスのパフォーマンスが低下するため、可能な限り回避する必要があります。パスごとに異なる条件が本当に必要な場合は、これらを個別のシェーダー プログラムに分割し、制御フローに均一なものを使用するのではなく、必要に応じてプログラムを交換します。

また、gl_FragColor に繰り返し書き込むことが、ここで実行できる最速の方法であるかどうかもわかりません。lowp または mediump の中間色変数を使用し、それにガウス コンポーネントを追加し、完了したら最終結果を gl_FragColor に書き込みます。

サンプリング オフセットの計算を頂点シェーダーに移動し、それらのオフセットをフラグメント シェーダーに渡したことがわかります。これは、人々が通常見逃している良いことです。上記の調整を実装すると (またはフレームワークでこれを処理する方法を試してみると)、フィルタリングからより良い結果が得られるはずです。

于 2013-04-06T16:04:42.567 に答える