2

フラグメントシェーダーに次のコードがあります。

precision lowp float;

varying vec2 v_texCoord;
uniform sampler2D s_texture;

uniform bool color_tint;
uniform float color_tint_amount;
uniform vec4 color_tint_color;

void main(){
    float gradDistance;
    vec4 texColor, gradColor;
    texColor = texture2D(s_texture, v_texCoord);
    if (color_tint){
        gradColor = color_tint_color;
        gradColor.a = texColor.a;
        texColor = gradColor * color_tint_amount + texColor * (1.0 - color_tint_amount);
    }
    gl_FragColor = texColor;
}

color_tintコードは正常に機能しますが、渡したものがすべてfalseであっても、上記のコードによってパフォーマンスが大幅に低下するのは興味深いことです。比較する場合:

void main(){
    float gradDistance;
    vec4 texColor, gradColor;
    texColor = texture2D(s_texture, v_texCoord);
    if (false){
        gradColor = color_tint_color;
        gradColor.a = texColor.a;
        texColor = gradColor * color_tint_amount + texColor * (1.0 - color_tint_amount);
    }
    gl_FragColor = texColor;
}

後者は40+fpsを達成できますが、最初のものは約18fpsです。私はダブルチェックcolor_tintしましたが、最初に渡されたものはすべてfalseであるため、ブロックは実行されません。

ところで、私はGLES20を使用してAndroid2.2で上記をプログラミングしています。

シェーダーの何が問題になっているのか、専門家は知っていますか?

4

2 に答える 2

6

フラグメントシェーダーではブランチが非常に遅いため、可能であればブランチを避けてください。色合いがない場合は、color_tint_amountの0を使用します。color_tint_colorを事前に乗算し、ピクセルごとの乗算を保存します。color_tint_amount=1.0-color_tint_amountにします。(つまり、1.0はgradColorがないことを意味します)これらのシェーダーは1秒間に何百万回も実行されるため、可能な限りすべてのサイクルを保存する必要があります。

于 2011-05-04T05:47:46.880 に答える
6

私はフラグメントシェーダーの専門家ではありませんが、2番目のシェーダーは、真ではないため、コンパイル時にifステートメント全体を削除できるため、より高速になると思います。最初のものでは、実行時まで常にfalseであるとは言えないcolor_tintため、毎回チェックして分岐する必要があります。ブランチは、特に予測可能なシリアルプログラミング用に設計されていることが多いグラフィックハードウェアでは、高価になる可能性があります。

ブランチレスになるように書き直してみることをお勧めします-ダレンの答えには、その方向にいくつかの良い提案があります。

于 2011-05-04T06:17:33.513 に答える