Bagaimana cara memuat potongan susun dengan cepat?

8

Saat ini saya sedang mengerjakan dunia tanpa batas, sebagian besar terinspirasi oleh minecraft.
Sebuah Chunk terdiri dari 16x16x16 blok. Blok (kubus) adalah 1x1x1.

Ini berjalan sangat lancar dengan ViewRange 12 Potongan (12x16) di komputer saya. Baik.
Ketika saya mengubah tinggi Chunk ke 256, ini menjadi - jelas - laggy yang luar biasa.

Jadi pada dasarnya yang ingin saya lakukan adalah menumpuk potongan. Itu berarti duniaku bisa [∞, 16, ∞] Bongkahan besar.

Pertanyaannya sekarang bagaimana cara menghasilkan bongkahan dengan cepat?
Saat ini saya menghasilkan tidak ada potongan melingkar di sekitar posisi saya (dekat ke jauh). Karena saya belum menumpuk, ini tidak terlalu rumit.

Sebagai catatan penting di sini: Saya juga ingin memiliki bioma, dengan tinggi min / maks berbeda. Jadi di Biome Flatlands , lapisan tertinggi dengan balok adalah 8 (8x16) - di Pegunungan Biome lapisan tertinggi dengan balok adalah 14 (14x16). Seperti contohnya.

Apa yang bisa saya lakukan adalah memuat 1 Chunk di atas dan di bawah saya misalnya.
Tetapi di sini masalahnya adalah, bahwa transisi di antara bioma yang berbeda dapat lebih besar dari satu potongan pada y.




Transisi antar Bioma




Pemuatan chunk saya saat ini sedang beraksi

Contoh Pemuatan Potongan



Untuk kelengkapan di sini "algoritma" pemuatan potongan saya saat ini

private IEnumerator UpdateChunks(){
    for (int i = 1; i < VIEW_RANGE; i += ChunkWidth) {
        float vr = i;
        for (float x = transform.position.x - vr; x < transform.position.x + vr; x += ChunkWidth) {
            for (float z = transform.position.z - vr; z < transform.position.z + vr; z += ChunkWidth) {

                _pos.Set(x, 0, z); // no y, yet
                _pos.x = Mathf.Floor(_pos.x/ChunkWidth)*ChunkWidth;
                _pos.z = Mathf.Floor(_pos.z/ChunkWidth)*ChunkWidth;

                Chunk chunk = Chunk.FindChunk(_pos);

                // If Chunk is already created, continue
                if (chunk != null)
                    continue;

                // Create a new Chunk..
                chunk = (Chunk) Instantiate(ChunkFab, _pos, Quaternion.identity);
            }
        }
        // Skip to next frame
        yield return 0;
    }
}
Brettetete
sumber

Jawaban:

1

Apa yang perlu Anda pertimbangkan memuat / membuat satu potongan di atas dan di bawah permukaan dalam tumpukan yang diberikan saat pemain berada di permukaan, sehingga algoritme generasi Anda perlu khawatir tentang tumpukan di tingkat atas daripada potongan ... saat pemain di bawah tanah satu di atas dan di bawah level chunk saat ini baik-baik saja. Untuk memperjelas, tumpukan adalah kolom vertikal potongan dari batuan dasar ke stratosfer :)

Cara lain untuk melihatnya adalah dengan mengatakan jika permukaan di bawah level chunk pemain saat ini - hasilkan permukaan dan satu di bawah, jika tidak, hasilkan level saat ini dan satu di atas dan di bawah.

Jadi misalkan dunia Anda akan mencapai 256 chunks (* 16 = 4096 blok voxel), dan kapan saja jika stack berada dalam jangkauan view, Anda akan memiliki 1 hingga 3 chunks dalam stack yang benar-benar dimuat dan di-render.

Bioma memperkenalkan masalah tambahan memadukan ketinggian di bagian tepinya, tetapi Anda dapat mengatasinya dalam kode spesifik bioma yang akan dipanggil untuk menghasilkan fitur permukaan dan bawah permukaan. Jika Anda menggunakan perlin / simplex noise untuk menghasilkan ketinggian, jika chunk berbatasan chunk yang merupakan bioma yang berbeda, Anda bisa mendapatkan nilai noise yang dihasilkan oleh kedua tipe bioma, kemudian rata-rata.

Ascendion
sumber
0

Apa yang dapat Anda lakukan adalah membuat potongan 256 dalam arah y dan membaginya menjadi 16 bagian, masing-masing menjadi 16 blok. Anda kemudian menghasilkan data untuk chunk, dan membangun geometri di dalam bagian.

Salah satu keuntungannya adalah, Anda memiliki akses ke data chunk yang lengkap, yang membuatnya lebih mudah untuk mengakses data di atas dan di bawah bagian.

Ini juga memiliki keuntungan karena dapat dengan mudah menyisihkan banyak geometri yang tidak terletak di dalam frustasi penglihatan. Juga akan ada banyak bagian yang tidak memiliki geometri sama sekali.

Jika Anda belum menggunakannya, memuat potongan di utas lain juga dapat memberi Anda frame rate yang lebih baik, sambil menghasilkan data untuk setiap chunk.

user000user
sumber
1
Yah, mungkin saya sudah menjelaskan diri saya agak kabur. Saya sudah merencanakan untuk memisahkan satu potong menjadi 16 lapisan. Tetapi bagaimana cara saya memutuskan lapisan mana yang akan dimuat? Setiap bioma memiliki tinggi minimum / min. Imagine Biome A [100,20] Biome B [160.200] - Saya berada di ujung kedua bioma. Mereka memiliki transisi yang mulus. Bagaimana cara memutuskan lapisan mana yang akan dimuat? Tetapi ketika menulis ini saya pikir saya hanya perlu memeriksa setiap lapisan (dari atas ke bawah) dan membuatnya, ketika lapisan di atas kosong / transparan - dan berhenti ketika lapisan pertama dibuat. Semoga Anda mendapatkan ini;) Ini mengganggu Anda tidak dapat menambahkan baris kosong dalam komentar
Brettetete
3
Saya mengerti maksud Anda. Tetapi jika Anda menerapkan algoritma seperti greedy meshing, Anda harus dapat memuat semua lapisan tanpa kehilangan kinerja yang sangat besar. Anda dapat menemukan artikel tentang ketamakan rakus di sini . Saya melakukan hal yang sama di mesin voxel saya dan itu berfungsi dengan baik sejauh ini.
user000user
Teknik ini sangat menakjubkan. Saya akan mencoba menerapkan ini ke mesin saya. Kode yang diberikan agak aneh, apakah Anda akan membagikan implementasi Anda? :)
Brettetete
2
Saya menempelkan implementasi C ++ saya di sini dan menambahkan beberapa komentar. Semoga membantu :)
user000user
Luar biasa, ini sepertinya sangat membantu. Terima kasih! Saya akan mencoba menerjemahkan ini sekarang. Tetapi pada # 67 - # 68 ada dobel && - apakah Anda melewatkan / menggandakan sesuatu secara tidak sengaja untuk disalin? :) Dan bisakah Anda segera menjelaskan / memposting metode SHIFT_ ? Juga saya tidak melihat pernyataan / penggunaan tmp - Ya, sory untuk semua pertanyaan itu
Brettetete
0

Saya tidak percaya Anda dapat melakukan ini hanya dengan memuat lapisan tertentu karena masalah transisi.

Kecenderungan saya adalah menyimpan beberapa metadata dengan setiap chunk:

1) Apakah blok sepenuhnya udara. Jika demikian, tidak perlu untuk membuatnya.

2) Untuk setiap muka balok apakah buram. Wajah buram berarti Anda tidak perlu mempertimbangkan potongan berikutnya. (Namun, perhatikan bahwa tergantung pada di mana bongkahan itu ada, mungkin ada sebanyak tiga wajah yang terlibat - bongkahan harus diberikan jika salah satu dari ketiganya tidak buram. Saya menduga ini adalah yang terbaik yang dihitung sebelumnya - render begitu lama b1 terlihat dan memiliki wajah non-buram f1 atau b2 terlihat memiliki wajah non-buram f2 atau b3 terlihat memiliki wajah non-buram f3.)

Sayangnya ada lebih dari 7000 bongkahan dalam rentang penglihatan 12 bongkahan. Namun, saya berharap beberapa lokasi memiliki lebih dari tiga bongkahan vertikal yang sebenarnya perlu dirender menggunakan pendekatan ini yang memotong jumlah bongkahan menjadi mungkin tidak lebih dari 1500.

Saya akan menerapkan jenis logika yang sama di dalam chunk - ketika Anda memuat chunk menghitung persimpangan apa yang transparan dan persimpangan apa yang opak menyentuh buram - Anda hanya perlu benar-benar membuat wajah di mana seseorang dapat melihatnya. (Perhatikan bahwa di Minecraft Anda memiliki tiga jenis blok - transparan, buram dan mengubah visi - kaca, pintu, pagar, dll. Anda hanya dapat melewati transparan-transparan dan buram-buram.)

Loren Pechtel
sumber