Cara menangani bahan dalam sistem Entity / Komponen


13

Implementasi E / C saya adalah yang mendasar di mana Entitas hanya ID, Komponen adalah data, dan Sistem bertindak atas Data. Saat ini saya mengalami masalah dengan material objek dan rendering secara umum. Untuk objek sederhana, saya memiliki ModelComponent, terkait dengan RenderSystem, ModelComponentmemiliki id buffer vertex yang digunakan sistem render. Sederhana MaterialComponentmungkin akan memiliki kekuatan warna atau specular, dll, tapi saya ingin itu cukup fleksibel untuk memungkinkan lebih dari satu render pass dan "efek" umum yang tidak semudah variabel sederhana di MaterialComponent.

Mencoba memecahkan masalah ini, saya menemukan dua solusi:

1 - Komponen Bahan Super-generik

Sesuatu seperti ini:

struct Material : public Component
{
    ShaderData* shader;
    std::vector<std::pair<std::string, boost::any>> uniforms;
    [...]
};

dan dalam sistem render saya akan mengulang dan menyerahkan seragam ke shader. Saya kira ini akan lambat, tetapi cukup cepat untuk tujuan saya.

2 - Lapisan abstraksi lainnya, MaterialData

Memiliki kelas untuk membungkus bahan tertentu, yang bisa diwarisi oleh bahan khusus apa pun, kelas dasar akan memiliki sesuatu seperti void set_shader_constants(ShaderData* d)tetapi implementasinya terserah masing-masing kelas, dan MaterialComponentakan memiliki pointer ke objek MaterialData.

Saya tidak yakin pendekatan mana yang saya inginkan, tetapi tidak satu pun dari ini menyentuh subjek beberapa pass, atau teknik rendering kompleks lainnya.

Adakah cara untuk mencapai ini?

Jawaban:


26

Materi adalah konsep grafis, dan termasuk dalam penyaji Anda. Renderer adalah arsitektur dengan level yang terlalu rendah untuk dibangun di atas sistem entitas. Sistem entitas harus untuk objek game tingkat tinggi. Tidak semuanya perlu menjadi komponen, dan pada kenyataannya, itu umumnya ide yang buruk untuk mencoba memaksa semuanya menjadi paradigma tunggal seperti itu. Ini menciptakan solusi denominator yang paling tidak umum.

Karenanya saya akan menyarankan Anda mengambil pendekatan yang berbeda:

  • Materi hanyalah tipe lain dalam renderer Anda.
  • Penyaji Anda memiliki tipe yang mewakili "sesuatu untuk ditarik ke layar." Seringkali ini disebut "render instance" atau "renderables" atau bahkan "models." Jenis ini memiliki referensi ke materi yang akan digunakan saat menggambar dan menyediakan API publik untuk memungkinkan konsumen pemberi render untuk mengatur materi itu untuk apa pun yang diinginkan.

Ini pada dasarnya meminta Anda untuk mengambil ModelComponentdan mengganti nama Model, menghapus ketergantungan pada entitas / lapisan komponen dan dengan demikian memindahkannya ke lapisan abstraksi yang lebih rendah, di samping sisa penyaji Anda.

Kemudian, Anda melakukan ini:

  • Pada lapisan abstraksi yang sama dengan komponen Anda yang lain, Anda memiliki semacam "komponen aspek" yang mewakili presentasi visual suatu entitas. Komponen ini hanya berisi referensi ke beberapa renderable (seperti dijelaskan di atas), yang pada gilirannya berisi referensi ke suatu bahan. Komponen dapat menyediakan API untuk mengekspos renderable (sehingga memungkinkan klien untuk memanipulasinya) atau mungkin membungkus API renderable untuk mengontrol eksposur. Terserah kamu.

Ini membahas masalah saling ketergantungan komponen yang Anda hadapi dengan memiliki model dan material yang keduanya menjadi komponen; suatu entitas harus memiliki aspek atau tidak, dan aspek itu harus dapat menyandikan segala sesuatu tentang penyajian entitas, termasuk materi.

Ini juga memberi Anda fleksibilitas untuk mengambil pendekatan lain dengan objek material yang akan lebih sulit dilakukan dengan objek itu sebagai komponen karena kurangnya paritas dengan sisa abstraksi sistem render.

Masalah Anda untuk memungkinkan efek yang lebih kompleks dan beberapa lintasan adalah salah satu yang bisa dipecahkan terutama dalam materi, dengan mengekspos fungsi ke kueri dan menetapkan konstanta shader bernama yang diekspos oleh file shader material. Ini terutama benar jika Anda menggunakan file efek (dalam D3D) yang mendukung banyak lintasan dan sejenisnya. Bahkan jika Anda tidak menggunakan file efek, Anda dapat mengekspos ide beberapa lintasan dari materi, masing-masing dengan shader yang berbeda, dan memungkinkan API materi untuk menyediakan manipulator untuk itu. Akan lebih mudah dan lebih bersih untuk berintegrasi ke dalam rendering API yang paling mungkin, karena materi sekarang berada pada tingkat abstraksi yang sama.


1
Terima kasih atas jawaban Anda, masalah ini mengganggu saya selama beberapa waktu, tetapi membuat penyaji tanpa kendala E / C jauh lebih mudah.
Luke B.
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.