openGL で 2D ゲームを作成しています。ウィンドウ全体を覆ういくつかのテクスチャをレンダリングしているときに、いくつかのパフォーマンスの問題が発生しました。
私が実際に行っているのは、画面のサイズでテクスチャを作成し、FBO を使用してシーンをそのテクスチャにレンダリングし、異なるオフセットでテクスチャを数回レンダリングして、一種の「影」を作成することです。しかし、そうすると、内蔵ビデオ カードを使用しているときにパフォーマンスが大幅に低下します。
したがって、全体として、画面全体に7つのクワッドをレンダリングします(背景画像、黒い「色合い」の5つの「影画像」、および真の色の同じテクスチャ)。サイズが 1024x1024 で、900x700 のウィンドウに収まる RGBA テクスチャを使用しています。テクスチャをレンダリングしていないときは 200 FPS、レンダリングしているときは 34 FPS を取得しています (両方のシナリオで、実際にテクスチャを作成し、シーンをレンダリングします)。基本的に 7 つのクワッドしかレンダリングしていないため、これは非常に奇妙です。奇妙なことは、CPU プロファイラーを実行しても、これがボトルネックであることを示唆していないことです (opengl はパイプライン アーキテクチャを使用しており、これが発生する可能性があることは知っていますが、ほとんどの場合は発生しません)。
外部ビデオ カードを使用すると、上記のテストを実行すると、一貫して 200 FPS が得られます。しかし、テクスチャへのシーン レンダリングを無効にし、画面へのテクスチャ レンダリングを無効にすると、~1000 FPS になります。これは、外部ビデオ カードでのみ発生します。統合ビデオ カードを使用して FBO を無効にすると、同じ 200 FPS になります。これは本当に私を混乱させます。
何が起こっているのか、また上記の数字が正しいかどうかを説明できる人はいますか?
内蔵ビデオ カード - Intel HD Graphics 4000
外付けビデオカード - NVIDIA GeForce GTX 660M
PS私はC#でゲームを書いているので、それが役に立ったらOpenTKを使います。
編集:
まず第一に、すべての回答に感謝します。それらはすべてある意味で非常に役に立ちましたが、残念ながら、単に「コードを簡素化/最適化する」だけでは不十分だと思います。レンダリング コードの一部を共有させてください。
//fields defined when the program is initialized
Rectangle viewport;
//Texture with the size of the viewport
Texture fboTexture;
FBO fbo;
//called every frame
public void Render()
{
//bind the texture to the fbo
GL.BindFramebuffer(FramebufferTarget.Framebuffer, fbo.handle);
GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, fboTexture,
TextureTarget.Texture2D, texture.TextureID, level: 0);
//Begin rendering in Ortho 2D space
GL.MatrixMode(MatrixMode.Projection);
GL.PushMatrix();
GL.LoadIdentity();
GL.Ortho(viewport.Left, viewport.Right, viewport.Top, viewport.Bottom, -1.0, 1.0);
GL.MatrixMode(MatrixMode.Modelview);
GL.PushMatrix();
GL.LoadIdentity();
GL.PushAttrib(AttribMask.ViewportBit);
GL.Viewport(viewport);
//Render the scene - this is really simple I render some quads using shaders
RenderScene();
//Back to Perspective
GL.PopAttrib(); // pop viewport
GL.MatrixMode(MatrixMode.Projection);
GL.PopMatrix();
GL.MatrixMode(MatrixMode.Modelview);
GL.PopMatrix();
//Detach the texture
GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, fboTexture, 0,
0, level: 0);
//Unbind the fbo
GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0);
GL.PushMatrix();
GL.Color4(Color.Black.WithAlpha(128)); //Sets the color to (0,0,0,128) in a RGBA format
for (int i = 0; i < 5; i++)
{
GL.Translate(-1, -1, 0);
//Simple Draw method which binds the texture and draws a quad at (0;0) with
//its size
fboTexture.Draw();
}
GL.PopMatrix();
GL.Color4(Color.White);
fboTexture.Draw();
}
したがって、fbo とテクスチャへのレンダリングに実際に問題があるとは思いません。これは、両方のカードでプログラムの速度が低下する原因ではないためです。以前はフレームごとに fbo を初期化していたため、Nvidia カードの速度が低下した可能性がありますが、すべてを事前に初期化すると、fbo の有無にかかわらず同じ FPS が得られます。
テクスチャを無効にしてテクスチャのない四角形をレンダリングすると同じ結果が得られるため、一般的にテクスチャには問題がないと思います。それでも、画面全体をカバーする場合でも、画面に 7 つのクワッドのみをレンダリングする場合、統合カードは 40 FPS よりも高速に動作するはずだと思います。
これを実際にプロファイリングして結果を返信するにはどうすればよいか、ヒントを教えてください。それは本当に役に立ちます。
編集2:
OK、少し実験したところ、はるかに優れたパフォーマンスを得ることができました。最初に、最終的なクワッドをシェーダーでレンダリングしてみましたが、期待したほどパフォーマンスに影響はありませんでした。
次に、プロファイラーを実行しようとしました。しかし、私の知る限り、SlimTune は単なる CPU プロファイラーであり、望んでいた結果が得られませんでした。次に、gDEBugger を試してみました。Visual Studio と統合されていますが、後で .NET プロジェクトをサポートしていないことがわかりました。外部バージョンを実行してみましたが、うまくいかないようでした (ただし、十分に遊んでいないだけかもしれません)。
本当にうまくいったのは、7 つのクワッドを画面に直接レンダリングするのではなく、最初にテクスチャでレンダリングし、再び fbo を使用してから、最終的なテクスチャを画面に一度レンダリングしたことです。これで fps が 40 から 120 になりました。テクスチャへのレンダリングは、画面への直接レンダリングよりも高速なのはなぜですか? それにもかかわらず、みんなの助けに感謝します-私は私の問題を解決したようです. 誰かが状況の合理的な説明を思いついたら、本当に感謝します.