Bagaimana agar balok dilihat oleh pemain?

15

Saya sedang menulis game mirip Minecraft menggunakan mesin Ogre dan saya punya masalah. Saya harus mengoptimalkan permainan saya, karena ketika saya mencoba menggambar 10.000 blok, saya punya 2 FPS ... Jadi, saya mendapat ide yang menghalangi tampilan pesawat dan menyembunyikan blok yang tidak terlihat. Tapi saya punya masalah - bagaimana saya tahu blok mana yang terlihat oleh pemain?

Dan - jika Anda mengetahui metode pengoptimalan lain untuk gim semacam itu, tulis apa dan bagaimana menggunakannya di Ogre.

m4tx
sumber

Jawaban:

16

Yah, Ogre sudah menerapkan pemusnahan frustum (yang pada dasarnya tidak menarik apa pun yang tidak bisa dilihat dari kamera) tapi saya pikir masalah Anda berbeda.

Anda seharusnya tidak benar-benar menampilkan 10.000 blok, apa yang biasa dilakukan (atau setidaknya, dalam beberapa minecraft berbasis Ogre3d seperti klon yang pernah saya lihat (yang saya buat juga), dan dalam aslinya) adalah membuat mesh ( dari beberapa daerah NxNxN potongan) yang memiliki wajah luar dari kubus ditampilkan. Artinya, ketika Anda meletakkan 2 kubus berdampingan, 2 wajah yang bersentuhan tidak dapat dilihat dan karenanya tidak perlu digambar.

Wajah-wajah ini juga harus digambar dalam bentuk seperti ini: http://www.ogre3d.org/tikiwiki/tiki-index.php?page=DynamicGrowingBuffers karena kartu video modern lebih menyukai satu mesh 100000 poligon dibandingkan 1000 mesh 100 poligon.

Elva
sumber
10

Ada beberapa aspek untuk masalah ini. Pertama, bagaimana Anda menggambar 10.000 blok Anda? Apakah Anda benar-benar menggambar mereka sebagai 10.000 objek terpisah? Jika demikian ini hampir pasti leher botol Anda, bukan kurangnya oklusi pemusnahan. Anda harus mengelompokkan blok-blok ini ke dalam jumlah yang lebih kecil dari jerat (mungkin beberapa ribu per mesh) untuk mengurangi panggilan draw.

Adapun pertanyaan Anda yang sebenarnya, ada tiga jenis penyumbatan oklusi yang muncul di benak Anda.

1) Blok di luar tampilan frustum. Ini berarti blok yang ada di belakang Anda atau dua sisi. Ogre sudah menghapus ini melalui pemusnahan tampilan frustum.

2) Blok yang 'bawah tanah' atau dikelilingi sepenuhnya oleh blok lain sehingga tidak dapat dilihat dari sudut manapun. Anda dapat mengidentifikasi ini dengan melihat blok tetangga yang sama. Jika semuanya solid, blok Anda disembunyikan. GPU seharusnya tidak pernah mendengar tentang blok ini - mereka harus dilewati ketika Anda membangun mesh yang mewakili permukaan Anda.

3) Blok yang ada di permukaan dan dapat dilihat dari beberapa posisi di level, tetapi yang saat ini disembunyikan oleh bukit (atau sesuatu). Ini adalah kasus paling sulit yang belum saya jawab sendiri, tetapi ada kemungkinan bagus bahwa permintaan oklusi perangkat keras dapat digunakan untuk kasus ini.

Ini plug yang tidak tahu malu, tapi saya punya perpustakaan yang cukup matang yang digunakan beberapa orang untuk mengembangkan klon Minecraft, termasuk beberapa menggunakan Ogre. Anda menentukan konten volume dan menghasilkan mesh permukaan yang kemudian dapat Anda render. Ini halaman beranda:

http://www.thermite3d.org/

Dan ini adalah video proyek orang lain yang menggunakannya:

http://www.youtube.com/watch?v=Jju6WRPEK7o

David Williams
sumber
4

Anda dapat menggunakan pemusnahan backface untuk menyisihkan simpul dan piksel terkait yang tidak menghadap pemain. Buffer kedalaman harus menangani sisanya. Blok 10k benar-benar tidak banyak, 5770 saya dapat membuat 100k verts pada 1500fps. Saya pikir Anda melakukan sesuatu yang sangat salah.

DeadMG
sumber
Saya setuju. Ini mungkin masalah dengan hal lain.
Notabene
1

Jika Anda memiliki 10.000 objek terpisah, bottleneck mungkin adalah jumlah primitif, bukan verteks, poligon, atau isi. Panggang objek Anda menjadi lebih sedikit jumlah objek poligon yang lebih tinggi untuk kecepatan.

Minecraft memiliki konsep balok batu, tetapi saya tidak dapat menemukan referensi saat ini.

Berikut ini juga eksperimen saya pada menggambar ton kubus dengan berbagai teknik. Belum termasuk baking (belum).

Jari Komppa
sumber
0

Apa yang saya lakukan adalah setelah saya membuat array blok saya, tetapi sebelum saya membuat simpul, saya menjalankan sub yang disebut UpdateBlockVisiblility.

Sub hanya memeriksa tetangga ke blok, dan memperbarui blok boolean facevisible sesuai.

#define BLOCKFACE_NORTH 0

#define BLOCKFACE_SOUTH 1 

etc etc etc

if(IsBlockAt(NorthOfBlock))
  Blocks[Whatever].facevisible[BLOCKFACE_NORTH] = false;

Maka saya hanya membuat simpul untuk wajah jika terlihat! Sederhana :)

BMW
sumber