Saya mencoba membuat mesin game 2D menggunakan OpenGL ES 2.0 (iOS untuk saat ini). Saya telah menulis layer Aplikasi pada Objective C dan RendererGLES20 yang terpisah berisi C ++. Tidak ada panggilan khusus GL yang dilakukan di luar renderer. Ini bekerja dengan sempurna.
Tapi saya punya beberapa masalah desain saat menggunakan shader. Setiap shader memiliki atribut dan seragam uniknya sendiri yang perlu ditetapkan tepat sebelum panggilan undian utama (glDrawArrays dalam kasus ini). Misalnya, untuk menggambar beberapa geometri yang akan saya lakukan:
void RendererGLES20::render(Model * model)
{
// Set a bunch of uniforms
glUniformMatrix4fv(.......);
// Enable specific attributes, can be many
glEnableVertexAttribArray(......);
// Set a bunch of vertex attribute pointers:
glVertexAttribPointer(positionSlot, 2, GL_FLOAT, GL_FALSE, stride, m->pCoords);
// Now actually Draw the geometry
glDrawArrays(GL_TRIANGLES, 0, m->vertexCount);
// After drawing, disable any vertex attributes:
glDisableVertexAttribArray(.......);
}
Seperti yang Anda lihat kode ini sangat kaku. Jika saya menggunakan shader lain, katakan efek riak, saya akan perlu untuk lulus seragam tambahan, attribs vertex dll. Dengan kata lain saya harus mengubah kode sumber rendererGLES20 render hanya untuk memasukkan shader baru.
Apakah ada cara untuk membuat objek shader benar-benar generik? Seperti Bagaimana jika saya hanya ingin mengubah objek shader dan tidak khawatir tentang kompilasi ulang sumber game? Adakah cara untuk membuat agnostik penyaji seragam dan atribut dll ?. Meskipun kita perlu meneruskan data ke seragam, apa tempat terbaik untuk melakukan itu? Kelas model? Apakah kelas model mengetahui seragam dan atribut khusus shader?
Berikut ini menunjukkan kelas Aktor:
class Actor : public ISceneNode
{
ModelController * model;
AIController * AI;
};
Kelas pengendali model: kelas ModelController {class IShader * shader; int teksturId; warna vec4; float alpha; struct Vertex * vertexArray; };
Kelas Shader hanya berisi objek shader, kompilasi dan menautkan sub-rutinitas dll.
Di kelas Game Logic, saya sebenarnya merender objek:
void GameLogic::update(float dt)
{
IRenderer * renderer = g_application->GetRenderer();
Actor * a = GetActor(id);
renderer->render(a->model);
}
Harap dicatat bahwa meskipun Actor memperluas ISceneNode, saya belum mulai mengimplementasikan SceneGraph. Saya akan melakukannya segera setelah saya menyelesaikan masalah ini.
Ada ide bagaimana cara memperbaikinya? Pola desain terkait dll?
Terima kasih sudah membaca pertanyaan.