Я намагаюся зробити 2D ігровий движок, використовуючи OpenGL ES 2.0 (iOS поки що). Я написав прикладний рівень в Objective C і окремий власний RendererGLES20 в C ++. Жоден специфічний виклик GL не проводиться за межами рендерінга. Це працює чудово.
Але у мене є деякі проблеми з дизайном при використанні шейдерів. Кожен шейдер має свої унікальні атрибути та обмундирування, які потрібно встановити безпосередньо перед основним викликом розіграшу (glDrawArrays в цьому випадку). Наприклад, для того, щоб намалювати деяку геометрію, я би зробив:
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(.......);
}
Як бачите, цей код надзвичайно жорсткий. Якби я використовував інший шейдер, скажімо ефект пульсації, мені потрібно було б пропустити додаткову форму, вершинні атрибути тощо. Іншими словами, мені доведеться змінити вихідний код візуалізації RendererGLES20 просто для включення нового шейдера.
Чи є спосіб зробити об'єкт шейдера абсолютно загальним? Як, що робити, якщо я просто хочу змінити об'єкт шейдера і не турбуватися про перекомпіляцію джерела гри? Будь-який спосіб зробити рендерінга агностиком уніформи та атрибутів тощо ?. Незважаючи на те, що нам потрібно передавати дані у формі, яке найкраще місце для цього? Клас моделі? Чи відомий модельний клас щодо уніформи та атрибутів, визначених за шейдером?
Наступні шоу Клас актора:
class Actor : public ISceneNode
{
ModelController * model;
AIController * AI;
};
Клас модельного контролера: клас ModelController {клас IShader * шейдер; int textId; відтінок vec4; плаваюча альфа; struct Vertex * vertexArray; };
Клас шейдерів просто містить об'єкт шейдера, компілюючи та пов'язуючи підпрограми тощо.
У класі Game Logic я фактично рендерирую об'єкт:
void GameLogic::update(float dt)
{
IRenderer * renderer = g_application->GetRenderer();
Actor * a = GetActor(id);
renderer->render(a->model);
}
Зауважте, що, хоча Actor розширює ISceneNode, я ще не почав впроваджувати SceneGraph. Я зроблю це, як тільки вирішу це питання.
Будь-які ідеї, як це покращити? Пов'язані моделі дизайну тощо?
Дякую, що прочитали запитання.