Я пытаюсь сделать движок 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 textureId; оттенок vec4; плавать альфа; struct Vertex * vertexArray; };
Класс Shader содержит только объект shader, компиляцию и компоновку подпрограмм и т. Д.
В классе Game Logic я фактически представляю объект:
void GameLogic::update(float dt)
{
IRenderer * renderer = g_application->GetRenderer();
Actor * a = GetActor(id);
renderer->render(a->model);
}
Обратите внимание, что, хотя Actor расширяет ISceneNode, я еще не начал реализовывать SceneGraph. Я сделаю это, как только решу эту проблему.
Есть идеи как это улучшить? Связанные шаблоны дизайна и т.д.?
Спасибо, что прочитали вопрос.