Конвейер рендеринга двигателей: создание шейдеров

Я пытаюсь сделать движок 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. Я сделаю это, как только решу эту проблему.

Есть идеи как это улучшить? Связанные шаблоны дизайна и т. Д.?

Ответы на вопрос(4)

Ваш ответ на вопрос