web-dev-qa-db-ja.com

Java 2D描画の最適なパフォーマンス

Java 2Dゲームを作成中です。組み込みのJava 2D描画ライブラリを使用しています。取得したGraphics2Dで描画しています。 JFrameのキャンバスからのBufferStrategyから(全画面表示される場合があります)BufferStrategyはダブルバッファリングされています。再ペイントはタイマーを介してアクティブに行われます。ただし、特にLinuxでは、パフォーマンスの問題があります。

また、Java2Dにはグラフィックバッファーを作成したりグラフィックスを描画したりする方法が非常に多く、正しいことを行っているかどうかはわかりません。グラフィックス2d.getDeviceConfiguration()。createCompatibleVolatileImageを試してみましたが、これは有望に見えますが、描画コードをそのコードに切り替えると高速になることを実際に証明するものはありません。

あなたの経験では、2DグラフィックスをJava 1.5+で画面にレンダリングする最も速い方法は何ですか?ゲームはかなり先にあるので、完全に切り替えたくないので注意してください。 OpenGLやゲームエンジンなど、さまざまな描画方法基本的に、グラフィックス2Dオブジェクトを使用して画面に描画する最速の方法を知りたいです。

31
Zarkonnen

私はあなたと同じ問題を抱えています。ここに私の投稿をチェックしてください:

Java2Dパフォーマンスの問題

パフォーマンス低下の理由と修正方法が示されています。ただし、すべてのプラットフォームで正常に機能するとは限りません。理由は投稿でわかります。

15
Consty

この投稿への回答、 Consty's への回答、そして私自身の研究の統合:

機能するもの:

  • GraphicsConfiguration.createCompatibleImageを使用して、描画しているものと互換性のある画像を作成します。これは絶対に必要です!
  • Canvas.createBufferStrategy経由のダブルバッファ描画を使用します。
  • 可能な場合は-Dsun.Java2d.opengl=Trueを使用して描画を高速化します。
  • スケーリングに変換を使用しないでください。代わりに、使用する画像のスケーリングされたバージョンをキャッシュします。
  • 半透明の画像は避けてください。ビットマスクされた画像は問題ありませんが、Java2Dでは半透明性が非常に高くなります。

私のテストでは、これらの方法を使用して、速度が10倍から15倍になり、適切なJava 2Dグラフィックスが可能になりました。

29
Zarkonnen

ここに私の頭の上からいくつかのヒントがあります。あなたがより具体的で、あなたがやろうとしていたことなら、私はもっと助けることができるかもしれません。ゲームのように聞こえますが、想定したくありません。

必要なものだけを描いてください!常に盲目的にrepaint()を呼び出すのではなく、repaint(Rect)やrepaint(x、y、w、h)などの兄弟をいくつか試してください。

アルファブレンディングは、画像やプリミティブのブレンディングにコストのかかる操作になる可能性があるため、十分に注意してください。

可能な限り事前レンダリング/キャッシュしてください。同じように何度も何度も円を描く場合は、BufferedImageに描画してから、BufferedImageを描画することを検討してください。あなたはスピードのためにメモリを犠牲にしています(典型的なゲーム/高パフォーマンスのグラフィック)

OpenGLの使用を検討し、LWJGLのJOGLを使用してください。 JOGLはよりJavaに似ていますが、LWJGLはOpenGLアクセスに加えてより多くのゲーム機能を提供します。 OpenGLは、Swingの場合よりも桁違いに(適切なハードウェアとドライバーを使用して)描画できます。

10
basszero

まだ言及されていない重要なものがあると思います。可能な限りすべてのイメージをキャッシュしてください。画面を横切って移動しているオブジェクトがあり、その外観がほとんど変わらない場合は、オブジェクトをイメージに描画し、フレームごとに新しい位置でイメージを画面にレンダリングします。オブジェクトが非常に単純なものであっても、そうしてください。どれだけの時間を節約できるかに驚かれるかもしれません。ビットマップのレンダリングは、プリミティブのレンダリングよりもはるかに高速です。

レンダリングのヒントを明示的に設定し、品質への配慮が許す場合はアンチエイリアスなどをオフにすることもできます。

3
DJClayworth

Javaを使用していくつかの基本的な描画アプリケーションを実行しました。グラフィックを多用するようなことは何もしていませんが、すべての「再描画」の呼び出しを適切に処理することをお勧めします。親コンテナで追加の再描画呼び出しを行うと、レンダリングの量が2倍になる可能性があります。

1
Brendan Cashman

私はこの質問を見てきました。誰かが私よりも良い答えを提供してくれることを願っています。

それまでの間、jdk 1.4のベータリリース後に書かれた Sunホワイトペーパー を見つけました。ランタイムフラグ(記事の下部)を含む、微調整に関するいくつかの興味深い推奨事項があります。

"SolarisおよびLinuxのランタイムフラグ

SDKのBeta 3リリース、バージョン1.4以降、Java 2Dは、ローカルまたはリモートのどちらの表示環境で作業しているかに関係なく、DGAが利用できない場合、デフォルトで画像をピクスマップに保存します。この動作をpmoffscreenフラグでオーバーライドします。

-Dsun.Java2d.pmoffscreen = true/false

このフラグをtrueに設定すると、DGAが使用可能であっても、オフスクリーンピクスマップサポートが有効になります。このフラグをfalseに設定すると、オフスクリーンピクスマップのサポートが無効になります。 オフスクリーンピクスマップサポートを無効にすると、いくつかのレンダリングの問題を解決できます。 "

1
Brendan Cashman

必ずダブルバッファリングを使用してください。最初にメモリ内の1つの大きなバッファーに描画し、すべての描画が完了したら画面にフラッシュします。

0
Tom

純粋に行きたくない場合の代替Java 2Dは、GTGEやJGameなどのゲームライブラリを使用して(Googleで検索)、グラフィックへの簡単なアクセスを提供し、ダブルバッファリングとはるかに簡単な描画コマンド。

0
Paul Sagor

覚えておくべきことがいくつかあります

1)更新中 このリンク は、repaintを呼び出すのに適したオプションである可能性があるswingtimersの使用方法を示しています。再描画を理解する(以前のポスターで述べたように、あまり作業を行わないようにするために重要です)。

2)1つのスレッドでのみ描画していることを確認します。複数のスレッドからUIを更新すると、厄介なことが発生する可能性があります。

3)ダブルバッファリング。これにより、レンダリングがスムーズになります。 このサイト はあなたのためにもっと良い情報を持っています

0
Steve g