Anda ingin memisahkan tingkat pembaruan (kutu logika) dan menggambar (render centang).
Pembaruan Anda akan menghasilkan posisi semua objek di dunia yang akan ditarik.
Saya akan membahas dua kemungkinan berbeda di sini, yang Anda minta, ekstrapolasi, dan juga metode lain, interpolasi.
1.
Ekstrapolasi adalah di mana kita akan menghitung posisi (prediksi) objek pada frame berikutnya, dan kemudian menyisipkan antara posisi objek saat ini, dan posisi objek pada frame berikutnya.
Untuk melakukan ini, setiap objek yang akan ditarik harus memiliki kaitan velocity
dan position
. Untuk menemukan posisi objek pada frame berikutnya, kita cukup menambahkan velocity * draw_timestep
ke posisi objek saat ini, untuk menemukan posisi prediksi frame berikutnya. draw_timestep
adalah jumlah waktu yang telah berlalu sejak centang render sebelumnya (alias panggilan undian sebelumnya).
Jika Anda membiarkannya di sini, Anda akan menemukan benda itu "berkedip" ketika posisi yang diprediksi tidak cocok dengan posisi aktual di bingkai berikutnya. Untuk menghapus kedipan, Anda dapat menyimpan posisi yang diprediksi, dan lerp antara posisi yang diprediksi sebelumnya dan posisi yang diprediksi baru pada setiap langkah undian, menggunakan waktu yang telah berlalu sejak centang pembaruan sebelumnya sebagai faktor lerp. Ini masih akan menghasilkan perilaku yang buruk ketika objek yang bergerak cepat tiba-tiba mengubah lokasi, dan Anda mungkin ingin menangani kasing khusus itu. Semua yang dikatakan dalam paragraf ini adalah alasan mengapa Anda tidak ingin menggunakan ekstrapolasi.
2.
Interpolasi adalah tempat kami menyimpan status dari dua pembaruan terakhir, dan interpolasi di antara mereka berdasarkan jumlah waktu saat ini yang telah berlalu sejak pembaruan sebelum terakhir. Dalam pengaturan ini, setiap objek harus memiliki yang terkait position
dan previous_position
. Dalam hal ini, gambar kami akan mewakili paling buruk satu tanda centang pembaruan di belakang gamestate saat ini, dan paling banter, pada kondisi yang sama persis dengan tanda centang pembaruan saat ini.
Menurut pendapat saya, Anda mungkin ingin interpolasi seperti yang saya jelaskan, karena lebih mudah dari keduanya untuk diterapkan, dan menggambar sebagian kecil dari satu detik (misalnya 1/60 detik) di belakang negara Anda saat ini diperbarui baik-baik saja.
Edit:
Jika hal di atas tidak cukup untuk memungkinkan Anda melakukan implementasi, berikut adalah contoh cara melakukan metode interpolasi yang telah saya jelaskan. Saya tidak akan membahas ekstrapolasi, karena saya tidak bisa memikirkan skenario dunia nyata di mana Anda harus lebih menyukainya.
Saat Anda membuat objek yang dapat digambar, itu akan menyimpan properti yang perlu digambar (yaitu, informasi keadaan yang diperlukan untuk menggambarnya).
Untuk contoh ini, kami akan menyimpan posisi dan rotasi. Anda mungkin juga ingin menyimpan properti lain seperti posisi koordinat warna atau tekstur (yaitu jika suatu tekstur bergulir).
Untuk mencegah data dari modifikasi saat render thread menggambar itu, (yaitu lokasi satu objek diubah saat render thread menggambar, tetapi semua yang lain belum diperbarui), kita perlu mengimplementasikan beberapa jenis buffering ganda.
Sebuah objek menyimpan dua salinannya previous_state
. Saya akan menempatkan mereka dalam array dan merujuk mereka sebagai previous_state[0]
dan previous_state[1]
. Itu juga membutuhkan dua salinannya current_state
.
Untuk melacak salinan buffer ganda yang digunakan, kami menyimpan variabel state_index
, yang tersedia untuk pembaruan dan undian utas.
Utas pembaruan pertama menghitung semua properti objek menggunakan data itu sendiri (struktur data apa pun yang Anda inginkan). Kemudian, itu menyalin current_state[state_index]
ke previous_state[state_index]
, dan menyalin data baru yang relevan untuk menggambar, position
dan rotation
ke current_state[state_index]
. Kemudian state_index = 1 - state_index
, untuk membalik salinan buffer ganda yang saat ini digunakan.
Segala sesuatu dalam paragraf di atas harus dilakukan dengan kunci yang diambil current_state
. Pembaruan dan undian utas mengambil kunci ini. Kunci hanya diambil selama penyalinan informasi negara, yang cepat.
Di untaian render, Anda kemudian melakukan interpolasi linier pada posisi dan rotasi seperti ini:
current_position = Lerp(previous_state[state_index].position, current_state[state_index].position, elapsed/update_tick_length)
Di mana elapsed
jumlah waktu yang telah berlalu di utas render, sejak kutu pembaruan terakhir, dan update_tick_length
adalah jumlah waktu yang dibutuhkan laju pembaruan tetap Anda per kutu (mis. Pada pembaruan 20FPS, update_tick_length = 0.05
).
Jika Anda tidak tahu apa Lerp
fungsi di atas, maka checkout artikel wikipedia tentang subjek: Linear Interpolasi . Namun, jika Anda tidak tahu apa itu lerping, maka Anda mungkin belum siap untuk mengimplementasikan pembaruan / gambar yang dipisahkan dengan gambar yang diinterpolasi.