2011-11-20 14 views
9

私は、網膜ディスプレイ上で非常によく走るゲーム(55-60fps)を持っています。 既存のシーンとブレンドするフルスクリーンオーバーレイを追加したいとします。ただし、小さなテクスチャを使用しても、パフォーマンスが大幅に低下します。これを有効にするために実行できる最適化はありますか?大きなクワッドを融合させたときにパフォーマンスが低下する

私が80x120テクスチャを使用している場合(テクスチャはその場でレンダリングされるため、正方形ではありません)、私は25-30FPSになります。テクスチャを小さくするとパフォーマンスは向上しますが、品質は受け入れられません。しかし、一般的に、オーバーレイの品質はそれほど重要ではありません(それはちょうど照明です)。

レンダラーの使用率は99%です。

ファイル(.png)の正方形のテクスチャを使用しても、パフォーマンスが悪いです。

これは私がテクスチャを作成する方法である:

[EAGLContext setCurrentContext:context]; 

    // Create default framebuffer object. 
    glGenFramebuffers(1, &lightFramebuffer); 
    glBindFramebuffer(GL_FRAMEBUFFER, lightFramebuffer); 

    // Create color render buffer and allocate backing store. 
    glGenRenderbuffers(1, &lightRenderbuffer); 
    glBindRenderbuffer(GL_RENDERBUFFER, lightRenderbuffer); 
    glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8_OES, LIGHT_WIDTH, LIGHT_HEIGHT); 

    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, lightRenderbuffer); 

    glGenTextures(1, &lightImage); 
    glBindTexture(GL_TEXTURE_2D, lightImage); 

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, LIGHT_WIDTH, LIGHT_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); 

    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, lightImage, 0); 

そして、ここでは、レンダリングです...ここで

/* Draw scene... */ 

glBlendFunc(GL_ONE, GL_ONE); 


//Switch to offscreen texture buffer 
glBindFramebuffer(GL_FRAMEBUFFER, lightFramebuffer); 
glBindRenderbuffer(GL_RENDERBUFFER, lightRenderbuffer); 
glViewport(0, 0, LIGHT_WIDTH, LIGHT_HEIGHT); 

glClearColor(ambientLight, ambientLight, ambientLight, ambientLight); 
glClear(GL_COLOR_BUFFER_BIT); 

/* Draw lights to texture... */ 

//Switch back to main frame buffer 
glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebuffer); 
glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer); 
glViewport(0, 0, framebufferWidth, framebufferHeight); 

glBlendFunc(GL_DST_COLOR, GL_ZERO); 

glBindTexture(GL_TEXTURE_2D, glview.lightImage);  

/* Set up drawing... */ 

glDrawElements(GL_TRIANGLE_FAN, 4, GL_UNSIGNED_SHORT, 0); 

は、問題を絞り込むしようとしたとき、私が撮ったいくつかのベンチマークです。 'ブレンドなし'は、私がクワッドを描画する前にglDisable(GL_BLEND)を意味します。 'No buffer switching'は、描画する前にオフスクリーンバッファから前後に切り替わらないことを意味します。

(Tests using a static 256x256 .png) 
No blend, No buffer switching: 52FPS 
Yes blend, No buffer switching: 29FPS //disabled the glClear, which would artificially speed up the rendering 
No blend, Yes buffer switching: 29FPS 
Yes blend, Yes buffer switching: 27FPS 

Yes buffer switching, No drawing: 46FPS 

助けていただければ幸いです。ありがとう!代わりに、その後全体のライトマップをブレンドする

UPDATE

、私はその場で仕事をするためにシェーダを書いてしまいました。各フラグメントは、ライトマップのサンプルとブレンド(マルチテクスチャのようなもの)です。最初はパフォーマンスの向上はわずかでしたが、ライトマップにlowp sampler2dを使用したところ、約45FPSでした。

ここフラグメントシェーダです:

lowp vec4 texColor = texture2D(tex, texCoordsVarying); 
lowp vec4 lightColor = texture2D(lightMap, worldPosVarying); 
lightColor.rgb *= lightColor.a; 
lightColor.a = 1.0; 

gl_FragColor = texColor * color * lightColor; 
+0

私は 'glView'バッファを疑いますスイッチがおそらくここでの犯人です。これらの方法では何が起こっていますか? 'glBindRenderBuffer'を使わないのはなぜですか? – Justicle

+0

私はこれらの方法をインラインで説明します。 – whooops

+0

これでperf問題を解決するには、オーバーレイをプリレンダリングしてください(ちょうど今は静的にしておきます)、それをフレームごとにメインバッファにコピーしてみてください。それは、バッファスイッチが遅いかどうかを少なくとも教えてくれます(つまり、フレームごとにglBindFrame、glBindRender、glViewportを2回呼び出す)。 – Justicle

答えて

3

[OK]を、私はあなたがハードウェアの限界に直面して実行したと思います。画面全体のクワッドをシーン全体にブレンドすることは、おそらく、タイルベースのハードウェアにとって特に悪いケースです。 PowerVR SGX(iPhone上)は、必要がないときに物を描くのを避けるために、隠し面の除去に最適化されています。低消費電力デバイスに最適化されているため、メモリ帯域幅が狭くなっています。

したがって、画面サイズのブレンドされたクワッドが読み込まれ、すべてのフラグメントが画面に書き込まれています。おお!

glClearスピードアップは関連しています。GLには、レンダリング前にバックバッファの内容を気にしないので、前の内容をメモリにロードする必要がなくなります。

のiOSハードウェアの非常に良い概要はここにあります:実際のソリューションについてはhttp://www.imgtec.com/factsheets/SDK/POWERVR%20SGX.OpenGL%20ES%202.0%20Application%20Development%20Recommendations.1.1f.External.pdf

- 私は直接ゲームシーンであなたのオーバーレイをレンダリングしようとするだろう。例えば

、あなたのようになりますループをレンダリングする:あなたは、のPowerVRチップ上のレンダリングターゲットにレンダリングする別のに切り替えるレンダーターゲットとレンダリング、その後、以前のレンダーターゲットにあなたに戻す場合は

[EAGLContext setCurrentContext:context]; 

// Set up game view port and render the game 
InitGameViewPort(); 
GameRender(); 

// Change camera to 2d/orthographic, turn off depth write and compare 
InitOverlayViewPort() 

// Render overlay into same buffer 
OverlayRender() 
+0

ありがとうございます。そうです、私も同じような結論に達しました。残念ながら、私はあなたのソリューションを使用することはできません。私が描いているオーバーレイは本当にライトマップのほうが多いので、実際のゲーム環境のピクセルに影響します。私はかなり良い成功を収め、同じ仕事をするシェイダーを書くことになった。私はそのことの詳細を私の質問に掲示します。これを調査していただきありがとうございます! – whooops

+0

素晴らしい - 私はあなたが何をしたのが大好きです。 – Justicle

+0

私は自分のゲームで画面全体にブレンドされた画面サイズの四角形を使用しており、フレームレート(3Gでは30fps、網膜では60s)が落ちませんでした。減速は、テクスチャの作成にある可能性がありますか?フレームごとにやっていますか? – led42

1

パフォーマンスに大きな被害を与えます。この種のアクセスパターンには、最新のInstrumentsに組み込まれているOpenGL ESアナライザによって「論理バッファロード」というラベルが付けられています。

ライトマップレンダリングターゲットを最初に描画し、シーンをメインフレームバッファにレンダリングするようにレンダリング順序を変更した場合、ライトマップレンダリングターゲットテクスチャをフルスクリーンでブレンドしてパフォーマンスを大幅に向上させる必要があります。

0

iPad 1では、iOS 4.2を使用して、1つのフルスクリーンクワッドのGL_BLENDを18〜31フレーム/秒で有効/無効にすることができます。どちらのランでも、レンダラ使用率は90〜100%でした。

0

テクスチャを操作する前に、シェーダが最適化されていることを確認してください。 960x640スクリーン(614400ピクセル)を塗りつぶすとき、フラグメントシェイダーの操作は大きな影響を与えます。

この状況では、特定のバージョンのフラグメントシェーダーを作成することをお勧めします。

varying mediump vec2 vertexTexCoord; 
uniform sampler2D texture; 

void main() { 
    gl_FragColor = texture2D(texture, vertexTexCoord); 
} 

通常のプログラムを復元し、その後、このフラグメントシェーダで別のプログラムを作成し、あなたの大切なクワッドを描画する前にそれを使用します。このようなものでなければなりません。 iPhone 4は、1フレームあたり約1つのフルスクリーンの1:1テクスチャ付きクワッドをレンダリングでレンダリングできますが、より洗練されたシェーダで約1に急速に低下します。

(また、あなたのケースで、最初にオーバーレイテクスチャをレンダリングしようとし、その後、通常の要素、残りの部分の上に、テクスチャ。それは大きなマージンによって、パフォーマンスを向上させる必要があります。)

関連する問題