2016-06-26 56 views
0

さて、私は(LibGDXで)作っているゲームのアンドロイドアプリを開発しています。そして私は断片シェイダーを持っており、私は〜41 FPSを持っていることに気付きました。私は問題がどこにあるのかを知るためにコードを使っていましたが、arrayName [i]からarrayName [0]に配列をアクセスする方法を変更すると、ループは60 FPSに戻りました。この特定のインスタンス。
はここのコードです:この特定の場合にはGLSL:forループの配列にアクセスすると、パフォーマンスが低下する

#version 300 es 

precision highp float; 

uniform sampler2D u_texture; 

in vec2 vTexCoord0; 

struct BlackHole { 
    vec2 position; 
    float radius; 
    float deformRadius; 
}; 

uniform vec2 screenSize; 
uniform vec3 cameraPos; 
uniform float cameraZoom; 

uniform BlackHole blackHole[4]; 
uniform int count; 

out vec4 fragColor; 

void main() { 
    vec2 pos = vTexCoord0; 

    bool doSample = true; 

    for (int i = 0; i < count; i++) { 
     BlackHole hole = blackHole[i]; // <-------- blackHole is the array, and changing from [i] to [0] 
     vec2 position = (hole.position - cameraPos.xy)/cameraZoom + screenSize*0.5; 
     float radius = hole.radius/cameraZoom; 
     float deformRadius = hole.deformRadius/cameraZoom; 

     vec2 deltaPos = vec2(position.x - gl_FragCoord.x, position.y - gl_FragCoord.y); 
     float dist = length(deltaPos); 

     if (dist <= radius) { 
      fragColor = vec4(0, 0, 0, 1); 
      doSample = false; 
      break; 
     } else if (dist <= radius + 1.0) { 
      fragColor = vec4(1); 
      doSample = false; 
     } else if (dist <= deformRadius) {lensing 
      float distToEdge = deformRadius - dist; 
      pos += distToEdge * normalize(deltaPos)/screenSize; 
     } 
    } 

    if (doSample) 
     fragColor = texture(u_texture, pos); 
} 

、「カウントが」1
はGLSLのこのちょうど固有の特性ですか?または、いくつかの修正があります - "count"の最高値は4になるので、それを拡張してforループを使用することはできませんが、それは非常に良い解決策ではないように感じます。
なぜ、これが起こっているのか、それを修正する方法を知っていますか?

答えて

3

GLSL ES 3.0 specification、140ページ、「12.30ダイナミックインデックス」を参照してください:それは直接いくつかの実装によってサポートされていなかったので、配列、ベクトルと行列の動的なインデックスのサポートが義務付けられていなかった、GLSL ES 1.00の場合

を。ソフトウェアソリューション(プログラム変換による)は、一部のケースでは存在しますが、パフォーマンスの低下につながります。

OpenGL ES 3.0はまだすべてのデバイスでサポートされていないことに注意してください。現在のところ50% of all Android devices付近でサポートしています。ドライバ/コンパイラの実際の実装はまだ最適化されていないかもしれません。したがって、コードの実際の結果とパフォーマンスは、デバイスによって異なる可能性があります。

ダイナミックブランチとループを使用しないようにしてください(3.0より下のGLSL ESではコンパイルされません)。あなたのループが実行最大4倍であることがわかっている場合は、その値を定義するためにマクロを使用して:

#define COUNT 4 
... 
uniform BlackHole blackHole[COUNT]; 
... 
    for (int i = 0; i < COUNT; i++) { 

をあなたは、あなただけは4回のためにそれをコンパイルしながらループ2または3回を持っている必要がある場合は、残りのアイテムに値を入れて、そのアイテムが存在しないかのようにします(たとえば、半径をゼロに設定するなど)。これはまた、libgdx default shaderの仕組みです。

シェーダで分岐する場合も同じです。あなたのコードにはかなりの数のifelseがあります。それらを削除してみてください。私はあなたのコードを深く見ていませんが、例えばあなたのコードを変更することができます。分岐の代わりにsmoothstepとなります。

一般的なヒント:書き込むコードの影響をリアルタイムで示すシェーダーエディタを使用します。たとえば、PowerVR shader editorまたはAdreno shader editorです。これはあなたに大いに役立ちます。

+0

forループで追加の評価が必要だと思いますか? 'i Andreas

+0

いいえ、それは役に立たないでしょう。さらに108ページおよびhttps://www.khronos.org/files/opengles_shading_language.pdfを参照してください。 – Xoppa

+0

だから私はあなたがお勧めしたものを試しましたが、それはさらに遅くなりました - そして、私は#version 330 esを削除して、LibGDXシェーダのデフォルトバージョンに移そうとしました(OpenGL 2だと思います。もしそれが本当なら、それはまだ助けにならなかった)。 – KingDolphin

関連する問題