Floating point selalu merepotkan untuk presisi di dunia besar.
Artikel ini menjelaskan di balik layar dan menawarkan alternatif yang jelas - angka titik tetap. Beberapa fakta sangat mengesankan, seperti:
"Yah, 64 bit presisi membawa Anda ke jarak terjauh Pluto dari Matahari (7,4 miliar km) dengan presisi sub-mikrometer."
Baik presisi sub-mikrometer lebih dari kebutuhan fps (untuk posisi dan bahkan kecepatan), dan itu akan memungkinkan Anda untuk membangun dunia yang sangat besar.
Pertanyaan saya adalah, mengapa kita masih menggunakan floating point jika fixed point memiliki kelebihan seperti itu? Sebagian besar rendering API dan pustaka fisika menggunakan floating point (dan menderita kerugiannya, sehingga pengembang perlu menyiasatinya).
Apakah mereka jauh lebih lambat?
Selain itu, bagaimana menurut Anda mesin planet yang scalable seperti outerra atau infinity menangani skala besar? Apakah mereka menggunakan titik tetap untuk posisi atau apakah mereka memiliki algoritma pembagian ruang?
Jawaban:
Jika Anda mengizinkan saya plug yang tidak tahu malu, saya akan memberikan contoh dari game nyata yang sedang saya kerjakan (tautan video YouTube).
Gim ini memiliki dunia tanpa batas, yang dihasilkan secara prosedural pada mesin fisika. Ini menggunakan floating point presisi tunggal. Setelah beberapa ratus meter ruang permainan, masalah presisi mulai muncul (dan semakin semakin jauh dari asal Anda dapatkan).
Solusi saya? Setiap 200m atau lebih saya memindahkan seluruh dunia kembali sebesar 200m ke arah asal (jika Anda ingin menemukan dan mencoba salah satu prototipe di situs saya, dan membuka overlay debug [w] orld, Anda dapat melihat ini terjadi).
Mengapa tidak menggunakan titik tetap? Atau presisi ganda? Alih-alih presisi tunggal? Karena yang lainnya menggunakan floating point presisi tunggal!
Mesin fisika yang saya gunakan menggunakannya, XNA menggunakannya, data yang dimuat ke kartu grafis diformat sebagai titik mengambang presisi tunggal. Bahkan bahasa itu sendiri dirancang untuk bekerja dengan angka floating point - menulis dan (lebih penting) membaca
0.5f
jauh lebih mudah daripada0x80000000L
.Ini hanya masalah apa yang lebih mudah dalam praktik. Dan pemenang yang jelas adalah menyadari masalah presisi floating point dan menulis fungsi "pindahkan-dunia-kembali-ke-nol" yang cukup sederhana (atau mengimplementasikan partisi ruang atau apa pun yang sesuai dengan permainan Anda).
Dan akhirnya contoh lain - Orbiter adalah game (simulasi, sungguh) yang benar-benar perlu memperhatikan ketepatan. Tidak hanya di ruang angkasa tetapi juga dalam waktu (percepatan waktu plus benda yang mengorbit - tidak ingin mereka jatuh dari langit, sekarang). Ini juga menggunakan angka floating point dan menggunakan peretasan untuk menjaga stabilitas.
sumber
Pertama - ya, mereka secara signifikan lebih cepat. Bahkan jika Anda bisa mendapatkan titik tetap bekerja secepat FPU "normal", floating point nyata memiliki instruksi yang menguntungkan seperti fsel untuk berhenti bercabang, atau SIMD untuk bekerja pada banyak float sekaligus. GPU juga menggunakan floating point, setidaknya di antarmuka yang menghadap pengguna.
Kedua, 64 bit membuat Anda cukup jauh di floating point juga - kebanyakan orang masih menggunakan 32, tetapi keuntungan utama adalah bahwa ia berskala. Skala titik tetap itu memiliki akurasi tetap. Apakah Anda mengukur matahari ke Pluto, atau di seberang jalan, Anda mendapatkan ketepatan yang sama. Floating point akan memberi Anda hasil yang jauh lebih akurat ketika semua nilai yang terlibat lebih kecil. Karena perpustakaan fisika generik diharapkan bekerja setidaknya dengan lumayan banyak permainan pada skala yang berbeda - dan beberapa permainan itu sendiri mungkin memiliki skala yang sangat berbeda - mereka perlu menggunakan jenis angka yang bekerja pada banyak skala.
sumber
Poin penting lain yang harus dikemukakan adalah bahwa mengapung tidak begitu akurat karena orang-orang di sini tampaknya berpikir. Pelampung 32-bit memiliki 24-bit presisi integer penuh. Ini berarti paling tidak seakurat nilai titik tetap 24-bit untuk rentang apa pun yang diberikan. Sementara mengapung menjadi kurang akurat semakin besar nilainya, nilai titik tetap hanya akan meluap dan membungkus di beberapa titik. Mengurangi akurasi adalah fallback yang lebih baik. Mengapung juga bisa meluap, tetapi jauh, jauh di kemudian hari. Saya ingin melihat wajah Anda ketika dunia Anda tiba-tiba membungkus ke -2 ^ 31 karena titik tetap meluap.
Nilai floating point 64-bit memiliki presisi integer 53-bit, sehingga benar-benar akurat.
sumber
Dalam konteks FPS, nilai titik tetap mungkin sebenarnya merupakan liabilitas. Tutup ke nol floating-point lebih akurat. Hanya saja jarak yang lebih jauh dari titik tetap menjadi lebih disukai. Jawabannya sederhana bahwa itu tergantung pada konteks.
Dalam sesuatu seperti galaksi, Anda dapat menggunakan kerangka referensi. Gunakan skala besar untuk tata surya dan kemudian gunakan pusat Matahari (atau titik serupa) sebagai titik asal untuk apa pun di dalam sistem. Menggunakan sistem ini Anda dapat memiliki kue dan memakannya, sehingga untuk berbicara, dan itu tidak sulit untuk dibayangkan.
IIRC, dev Infinity mengatakan bahwa ia terus-menerus mengulangi masalah skala dalam salah satu wawancara.
sumber
Jika belum, Anda harus memeriksa tutorial Planet Rendering di GameDev.net. Adapun pembagian ruang, satu solusi adalah untuk menjaga dua variabel posisi yang terpisah - satu skala makro dan satu skala mikro. Ini bekerja dengan sangat baik (diuji).
Solusi yang tepat tergantung pada bagaimana Anda berencana untuk menangani jarak ekstrem di mesin - apakah Anda merencanakan gerbang lompatan, atau kompresi waktu?
sumber
Salah satu alasannya adalah bahwa aritmatika floating point adalah "cukup baik" (atau setidaknya sudah), itu menghasilkan hasil yang cukup akurat dengan cepat.
Selama Anda menyadari keterbatasan aritmatika floating point dan mengubah algoritma Anda untuk mengatasinya (lihat jawaban Andrew Russell) maka Anda akan menghasilkan kode yang "berfungsi".
sumber
Saya sedang menulis permainan. Dalam permainan / program saya, saya menggambar pesawat ruang angkasa di tempat asalnya menggunakan kamera yang cukup tetap dan planet saya menggambar menggunakan kamera terpisah. Dan dua hal ini menangani masalah saya, tetapi planet saya belum terlalu detail. Adapun solusinya Andrew Russell menyebutkan tentang menggerakkan dunia (dan saya berasumsi kamera dan penghuninya kembali ke tempat asalnya) saya benar-benar tidak akan mencobanya jika Anda pernah berencana menjadikan game ini game yang berjaringan. Jika Anda memindahkan dunia pada aplikasi server berdasarkan pada setiap gerakan klien maka dunia akan berakhir berjuang untuk suatu posisi. Dan akan mengambil posisi sepanjang waktu dari semua orang yang bermain yang akan menjadi kesalahan besar.
sumber