Pipeline de renderização do motor: fazendo shaders genéricos

Eu estou tentando fazer um motor de jogo 2D usando OpenGL ES 2.0 (iOS por enquanto). Eu escrevi Application layer no Objective C e um RendererGLES20 auto-contido separado em C ++. Nenhuma chamada específica de GL é feita fora do renderizador. Está funcionando perfeitamente.

Mas eu tenho alguns problemas de design ao usar shaders. Cada shader tem seus próprios atributos e uniformes exclusivos que precisam ser definidos antes da chamada da chamada principal (glDrawArrays, neste caso). Por exemplo, para desenhar alguma geometria, eu faria:

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(.......);
}

Como você pode ver este código é extremamente rígido. Se eu fosse usar outro sombreador, digamos ripple effect, eu precisaria passar uniformes extras, atributos de vértices, etc. Em outras palavras, eu teria que mudar o RendererGLES20 para renderizar o código fonte apenas para incorporar o novo sombreador.

Existe alguma maneira de tornar o objeto shader totalmente genérico? Como se eu apenas quisesse mudar o objeto shader e não se preocupar com a recompilação da fonte do jogo? Qualquer maneira de tornar o renderizador agnóstico de uniformes e atributos etc? Mesmo que precisemos passar dados para uniformes, qual é o melhor lugar para fazer isso? Modelo de classe? A classe do modelo está ciente dos uniformes e atributos específicos do shader?

Seguinte mostra Ator classe:

class Actor : public ISceneNode
{
    ModelController * model;
    AIController * AI;
};

Classe de controlador de modelo: classe ModelController {class IShader * shader; int textureId; vec4 matiz; flutuar alfa; struct Vertex * vertexArray; };

A classe Shader contém apenas o objeto shader, compilando e vinculando sub-rotinas etc.

Na classe Game Logic, estou renderizando o objeto:

void GameLogic::update(float dt)
{
    IRenderer * renderer = g_application->GetRenderer();

    Actor * a = GetActor(id);
    renderer->render(a->model);
}

Por favor, note que mesmo que o ator estenda o ISceneNode, ainda não comecei a implementar o SceneGraph. Eu farei isso assim que resolver este problema.

Alguma idéia de como melhorar isso? Padrões de design relacionados etc?

questionAnswers(4)

yourAnswerToTheQuestion