0

このフラグメント シェーダーを改善するにはどうすればよいですか。

  #ifdef GL_ES
precision mediump float;
#endif

varying vec4 v_fragmentColor;
varying vec2 v_texCoord;

uniform sampler2D u_texture;

uniform vec2 blurSize;
uniform vec4 substract;

  void main() {
    vec4 sum = vec4(0.0);
    sum += texture2D(u_texture, vec2(v_texCoord.x - 4.0 * blurSize.x, v_texCoord.y)) * 0.05;
    sum += texture2D(u_texture, vec2(v_texCoord.x - 3.0*blurSize.x, v_texCoord.y)) * 0.09;
    sum += texture2D(u_texture, vec2(v_texCoord.x - 2.0*blurSize.x, v_texCoord.y)) * 0.12;
    sum += texture2D(u_texture, vec2(v_texCoord.x - blurSize.x, v_texCoord.y)) * 0.15;
    sum += texture2D(u_texture, vec2(v_texCoord.x, v_texCoord.y)) * 0.16;
    sum += texture2D(u_texture, vec2(v_texCoord.x + blurSize.x, v_texCoord.y)) * 0.15;
    sum += texture2D(u_texture, vec2(v_texCoord.x + 2.0*blurSize.x, v_texCoord.y)) * 0.12;
    sum += texture2D(u_texture, vec2(v_texCoord.x + 3.0*blurSize.x, v_texCoord.y)) * 0.09;
    sum += texture2D(u_texture, vec2(v_texCoord.x + 4.0*blurSize.x, v_texCoord.y)) * 0.05;
    gl_FragColor = sum;    
}

線をぼかすのに使用しているので、ほとんどの場合、同じ色をブレンドしています。周囲の色が同じピクセルを無視する(背景色のままにする)ようにしたいと思います。どうすればそれができますか?

4

2 に答える 2

3

線の色のチェックを無視して、テクスチャ座標の計算を頂点シェーダーに移動し、変数として渡すことをお勧めします。たとえば、 をvec2(v_texCoord.x - 4.0 * blurSize.x, v_texCoord.y)頂点シェーダーに移動し、それをfirstTextureCoordinate可変として渡すことができます。

sum += texture2D(u_texture, firstTextureCoordinate) * 0.05;

フラグメントシェーダーで。

これには 2 つの重要な利点があります。1 つ目は、すべてのフラグメントに対して計算を実行するのではなく、この計算を頂点ごとに 1 回だけ実行し、その後、迅速なハードウェア補間を使用してそれをフラグメント シェーダーにフィードすることです。通常、頂点はフラグメントよりもはるかに少ないため、計算を節約できます。

2 つ目のおそらくより重要な利点は、iOS デバイスの PowerVR シリーズのようなタイルベースの遅延レンダラーで、変数として供給された座標からテクスチャ フェッチを行うことで、依存するテクスチャの読み取りを回避できることです。これにより、これらの GPU はテクスチャ フェッチで適切なキャッシングを行うことができ、この特定のハードウェアでパフォーマンスに大きな違いが生じることがわかりました。

いくつかの巧妙なロジックを使用すれば、テクスチャ フェッチの数を減らすことができるかもしれませんが、これは私が OpenGL ES フラグメント シェーダーのあらゆる場所で使用している単純な最適化であり、常に優れたパフォーマンスの向上をもたらします。

于 2012-08-14T15:07:41.333 に答える
1

シェーダーの多くの if-checks は NO GO です。

もう 1 つのオプションは、シェーダーに線の中心 (あなたの線のみの x 座標) を伝える均一 (または線が多い場合は均一配列) を追加することです。

シェーダーは、次のように単一の if チェックを持つことができます。

float spread = 4.0 * blurSize.x;
if(lineCentre-spread < gl_FragCoord.x && gl_FragCoord.x < lineCentre+spread){
   //You existing logic for blurr goes here.
}else{
    gl_FragColor = texture2D(u_texture, vec2(v_texCoord.x, v_texCoord.y)) * 0.16;
}

これにより、周囲にぼかしがかからない余白がたくさんある場合、全体的なパフォーマンスが向上します。

于 2012-08-14T08:21:01.807 に答える