OpenGL ESのしゃっくり。正しい実装は何ですか?
-
08-07-2019 - |
質問
OpenGL ESを使用して、iPhoneでゲームを作成しています。 残念ながら、小さな(不規則な)しゃっくりが見られます。
安定したフレームレートを保証するために、60秒ごとに描画機能を呼び出すスリープ付きタイマーを使用します。タイマーがスリープから復帰する時間を変更して、描画機能の実行時間を増やしました。しゃっくりは、描画関数がより多くの時間を与えられると少なくなります。 8ミリ秒では、アニメーションはほとんど流動的です。私の調査結果は次のとおりです。
- GPUに実際の描画を実行する時間を増やすと、(ほぼ)完全な滑らかなアニメーションになります。
- フレームの正確な最後に描画すると、スタッター、しゃっくりなどが発生します。
今、続行方法がわからないということがわかりました。この動作の原因について、2つの矛盾するアイデアがあります:
- 最初に、OpenGLコマンドが前のフレームの描画に干渉する可能性がありますか?コマンドが保存されており、描画コマンドが与えられます。
- 第二に、描画コマンドの変動する時間によってタイマーがティックをスキップする可能性がありますか?
では、どの説明がより可能性が高いのでしょうか?それともどちらでもありませんか?もちろん、描画関数を別のスレッドに入れて、問題が解決するかどうかを確認することもできます。しかし、OpenGLをもっと理解したいと思っています。
これは呼び出される関数であり、私が取っていることを説明しています:
- (void) drawView
{
// measure time with mach_absolute_time
// gameEngine update
// OpenGL commands (translate, rotate, drawArrays etc.)
// end measure time with mach_absolute_time
// usleep(animationInterval - duration - constant)
// constant is the time to start executing
// draw
glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
[context presentRenderbuffer:GL_RENDERBUFFER_OES];
}
解決
ゲームループに関する記事を読むとよいでしょう。一般的に、最善の解決策は、別のスレッド内の無限ループで描画ルーチンを呼び出すことです(この質問))、最後の更新からの経過時間に応じて、基礎となるゲームモデルを更新します。これにより、スムーズな動きが得られます。
編集:“しゃっくり”のソースに関しては、おそらくOpenGLとは関係ありません。 60  fpsでは、1/60秒で話しています≈フレームあたり17ミリ秒。デバイス上で他のプロセスが実行されているため、これは見逃しがちな厳しいスケジュールです。 SafariまたはMail.appがバックグラウンドで起動すると、デバイスはしばらくの間考え、現在は30ミリ秒以上かかります。モデルが完全に安定したフレームレートを期待している場合、これは非常に簡単に見つけることができます。解決策は、上で書いたように、経過したリアルタイムに従ってモデルを更新することです。リンクされた記事でこれについて詳しく説明しています。