GL ES:フラグメントシェーダーの最適化


8

概要: スプライトに色を付けようとするとすぐにFPSの速度が低下します(つまり、テクスチャをフラグメントシェーダーで色と乗算します)。

詳細:

ハードウェア:iPod touch 4

glDrawArraysを使用して画面に700のスプライトを描画しています。そして、はい、これらすべてを1回の描画呼び出しでバッチ処理しています。以下は、頂点データ構造を示しています。

struct Vertex {
    float Position[2];
    float Color[4];
    float Texture[2];
};

はい、いくつかのスプライトを選択的に着色する必要があるので、他のスプライトを選択的に着色する必要がないため、各頂点で色を送信しています。以下は私が使用しているフラグメントシェーダーです:

varying lowp vec2 TexCoord;
uniform sampler2D TextureSampler;

void main(void)
{
    gl_FragColor = texture2D( TextureSampler, TexCoord );
}

今までそれは素晴らしい仕事をしていて、私に完全な60 FPSを与えています!!!

だが

フラグメントシェーダーを次のように変更するとすぐに(着色を可能にするため):

varying lowp vec4 DestinationColor;
varying lowp vec2 TexCoord;
uniform sampler2D TextureSampler;

void main(void)
{
    gl_FragColor = texture2D( TextureSampler, TexCoord ) * DestinationColor;
}

アルファチャネルを含む次の64x64 pngテクスチャを使用して、glEnable(GL_BLEND)でレンダリングします。

ここに画像の説明を入力してください

性能のみ{だけと乗算することによって、この単一の変更に起因47 FPSに低下ONE(FPSは、Xcodeの機器とOpenGL探偵を使用して測定)ベクター}。何が起こっているのですか?

ありがとう。

編集:

また、頂点カラー属性ごとに削除してみました。

struct Vertex {
    float Position[2];
    float Texture[2];
};

また、フラグメントシェーダーを次のように変更します。

precision lowp float;
varying lowp vec2 TexCoord;
uniform sampler2D TextureSampler;

void main(void)
{
    gl_FragColor = texture2D( TextureSampler, TexCoord ) * vec4(1.0,0.0,0.0,1.0);
}

700のスプライトに対して52 FPSで実行されています(わずか5 FPSのゲイン)。したがって、これは補間ではなく、乗算は非常に高価なようです。この1つの乗算だけですか?


vsyncを有効にしていますか?数値は、変更後、他のすべてのvsyncが失われ始めることを意味し、平均で45 FPSになります。
msell 2013年

iPhone 4でテストしていますが、vsyncは既にデフォルトで有効になっていると思います。ちなみにxcode Instrumentsで47 FPSを示しているので、vsyncはまったく問題ではないと思います。しかし、私の本当の質問は、なぜパフォーマンスが低下するのか、そしてそれをどのように改善するのかです。
fakhir 2013年

1
テクスチャにアルファチャネルはありますか?テクスチャにアルファチャネルがなく、rgbにvec3が乗算されている場合、再び60 fpsで描画されますか?
2013年

はい、テクスチャにはアルファチャネルがあります。上に添付されているテクスチャをご覧ください。
fakhir 2013年

2
シングルコアSGX 535、GPUを備えた高DPIディスプレイは、それを処理することを意図していません。これらのデバイスのネイティブ解像度でのグラフィックスのパフォーマンスは常にひどいものでした。解像度を下げるか、30 fpsをターゲットにするか、新しいハードウェアをターゲットにする必要があります。あなたはそのGPUから奇跡を期待しています。タンクするのにそれほど時間はかかりません。
Sean Middleditch 2013年

回答:


2

パフォーマンスの問題は乗算で発生しているとは思いませんが、頂点シェーダーとフラグメントシェーダーの間の三角形全体の補間で発生していますDestinationColorfloat各スプライトのフラグメントごとに、ツリーの頂点間を補間する4つのがあります。

それぞれ64x64ピクセルの700のスプライトの場合、これはGPUに実行を要求しているフレームごとに 11468800の追加操作です。一部のvsyncが失われる可能性があり、そのため40フィッシュFPSに低下します。

頂点ごとに異なる色を使用して、各スプライトにグラデーションを設定できるようにすると、うまくいきません。他にも試してみたいトリックがいくつかありますが、そうではないと思います。

あなたがしているように見えるのは各スプライトに色を付けることなので、をに降格し、フラグメントシェーダーで直接使用DestinationColorしてuniform、呼び出しごとに変更できます。この方法では、補間は行われません。バッチ処理全体が失われますが、色で並べ替えると少しバッチ処理できる場合があります。


上記の質問を編集して、いくつかの詳細を追加しました。基本的に私は頂点カラーごとに剥ぎ取り、テクスチャをCONSTANTベクトルで単純に乗算してみました。つまり、次のとおりです。。52 FPS、ほぼ5 FPSのゲインを得ました。しかし、色合いがない場合と比較すると、速度が遅すぎます。単一のベクトルの乗算のみで8 FPSの速度が低下しますか?
2013年

3
ただし、これは単一の乗算ではありません。1フレームあたり約1100万です。
Maximus Minimus 2013年

1
@fakhir iPod Touch 4ディスプレイの解像度は960x640ピクセルです。合計で614400ピクセルです。700個のスプライトをそれぞれ64x64ピクセルでレンダリングするとします。これは2867200ピクセル、つまり画面全体の約5倍です。おそらく、元の60 fpsを取得したのは、オプティマイザが実行中の処理を把握し、画像を1回だけサンプリングした可能性があるからです。モバイルグラフィックプログラミングはデスクトッププログラミングよりもはるかに制限されているため、それに応じて行動してください。
パンダパジャマ2013年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.