Java 2D描画の最適なパフォーマンス
-
02-07-2019 - |
質問
私はJava 2Dゲームを書いています。私は組み込みのJava 2D描画ライブラリを使用しており、JFrameのCanvasからBufferStrategyから取得したGraphics2Dで描画しています(フルスクリーンの場合もあります)。 BufferStrategyはダブルバッファリングされています。再描画はタイマーを介して積極的に行われます。ただし、特にLinuxでパフォーマンスの問題が発生しています。
そして、Java2Dにはグラフィックスバッファを作成し、グラフィックスを描画する非常に多くの方法があるので、正しいことをしているかどうかはわかりません。 graphics2d.getDeviceConfiguration()。createCompatibleVolatileImageを試してみましたが、これは有望に見えますが、描画コードをそれに切り替えた場合に高速になることを実際に証明することはできません。
あなたの経験では、Java 1.5以降で2Dグラフィックスを画面にレンダリングする最も速い方法は何ですか?ゲームはかなり先のことなので、OpenGLやゲームエンジンなど、まったく異なる描画方法に切り替えたくないことに注意してください。基本的に、Graphics2Dオブジェクトを使用して画面にデータを描画する最速の方法を取得する方法を知りたいです。
解決
あなたと同じ問題を抱えています。ここで私の投稿をチェックしてください:
パフォーマンスの低下の理由と修正方法を示します。ただし、すべてのプラットフォームで正常に動作することは保証されていません。理由は投稿で確認できます。
他のヒント
この投稿への回答、 Consty's への回答、および私自身の研究の合成:
機能:
-
GraphicsConfiguration.createCompatibleImage
を使用して、描画対象と互換性のある画像を作成します。これは絶対に不可欠です! -
Canvas.createBufferStrategy
を介してダブルバッファ描画を使用します。 - 描画を高速化するために、可能な場合は
-Dsun.java2d.opengl = True
を使用します。 - スケーリングに変換を使用しないでください。代わりに、使用する画像のスケーリングされたバージョンをキャッシュします。
- 半透明の画像は避けてください!ビットマスクされた画像は問題ありませんが、Java2Dでは半透明性は非常に高価です。
これらのメソッドを使用したテストでは、10倍から15倍の速度向上が得られ、適切なJava 2Dグラフィックスが可能になりました。
ここに私の頭の上のいくつかのヒントがあります。あなたがより具体的で、あなたがしようとしていたことなら、私はもっと助けることができるかもしれません。ゲームのように聞こえますが、私は仮定したくありません。
必要なものだけを描いてください!常に盲目的にrepaint()を呼び出さないでください。repaint(Rect)やrepaint(x、y、w、h)などの兄弟を試してください。
アルファブレンディングは画像/プリミティブのブレンディングに費用のかかる操作になる可能性があるため、非常に注意してください。
可能な限りプリレンダリング/キャッシュしてみてください。同じ方法で何度も何度も円を描く場合は、BufferedImageへの描画を検討してから、BufferedImageを描画してください。速度のためにメモリを犠牲にしています(ゲームの典型的なもの/高性能グラフィックス)
OpenGLの使用を検討し、LWJGLのJOGLを使用します。 JOGLはJavaに似ていますが、LWJGLはOpenGLアクセスに加えてより多くのゲーム機能を提供します。 OpenGLは、(適切なハードウェアとドライバーを使用して)Swingができるよりも桁違いに描画できます。
まだ言及されていない重要なものがあります。できる限りすべての画像をキャッシュしてください。画面上を移動するオブジェクトがあり、その外観があまり変わらない場合は、それを画像に描画してから、フレームごとに新しい位置で画像を画面にレンダリングします。オブジェクトが非常に単純なものであっても、それを実行してください。時間をどれだけ節約できるかに驚くかもしれません。ビットマップのレンダリングは、プリミティブのレンダリングよりもはるかに高速です。
また、レンダリングのヒントを明示的に設定し、品質に関する考慮事項が許可されている場合はアンチエイリアスなどをオフにすることもできます。
Javaを使用して基本的な描画アプリケーションをいくつか作成しました。グラフィックを多用するものには取り組んでいませんが、すべての「再描画」呼び出しを適切に処理することをお勧めします。親コンテナでの追加の再描画呼び出しにより、レンダリングの量が2倍になる可能性があります。
私はこの質問を見てきました。誰かが私の質問よりも良い答えを提供してくれることを期待しています。
その間に、次の Sunホワイトペーパーを見つけましたa> jdk 1.4のベータリリース後に作成されました。ランタイムフラグなど、微調整に関する興味深い推奨事項がいくつかあります(記事の最後にあります):
" SolarisおよびLinuxの実行時フラグ
SDKバージョン1.4のBeta 3リリース以降、Java 2Dは、ローカルまたはリモートのディスプレイ環境で作業しているかどうかにかかわらず、DGAが利用できない場合にデフォルトでピックスマップに画像を保存します。 pmoffscreenフラグでこの動作をオーバーライドできます:
-Dsun.java2d.pmoffscreen = true / false
このフラグをtrueに設定すると、DGAが使用可能であっても、オフスクリーンピックスマップのサポートが有効になります。このフラグをfalseに設定すると、オフスクリーンピックスマップのサポートが無効になります。 オフスクリーンpixmapサポートを無効にすると、レンダリングの問題を解決できます。"
ダブルバッファリングを使用していることを確認し、最初にメモリ内の1つの大きなバッファに描画してから、すべての描画が完了したら画面にフラッシュします。
純粋なJava 2Dを使いたくない場合は、GTGEやJGame(Googleで検索)などのゲームライブラリを使用し、グラフィックスに簡単にアクセスし、ダブルバッファリングとより単純な描画を提供することもできます。コマンド。