Rendering renderowania silnika: generowanie shaderów

Próbuję stworzyć silnik gry 2D z wykorzystaniem OpenGL ES 2.0 (na razie iOS). Napisałem warstwę aplikacji w Objective C i oddzielną samodzielną RendererGLES20 w C ++. Żadne specyficzne połączenie GL nie jest wykonywane poza rendererem. To działa doskonale.

Ale mam problemy z projektowaniem podczas używania shaderów. Każdy moduł cieniujący ma swoje unikalne atrybuty i mundury, które należy ustawić tuż przed głównym wywołaniem drawa (w tym przypadku glDrawArrays). Na przykład, aby narysować geometrię, zrobiłbym:

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

Jak widać ten kod jest bardzo sztywny. Gdybym miał użyć innego modułu cieniującego, powiedzmy, efekt tętnienia, musiałbym przekazać dodatkowe mundury, atrybuty wierzchołków itp. Innymi słowy, musiałbym zmienić kod źródłowy renderowania RendererGLES20, aby włączyć nowy moduł cieniujący.

Czy jest jakiś sposób, aby obiekt shadera był całkowicie ogólny? Jak Co, jeśli chcę po prostu zmienić obiekt modułu cieniującego i nie martwić się o ponowne kompilowanie źródła gry? Jakikolwiek sposób na uczynienie renderującego agnostyka mundurów i atrybutów itp.? Chociaż musimy przekazywać dane do mundurów, jakie jest najlepsze miejsce, aby to zrobić? Klasa modelu? Czy klasa modelu jest świadoma mundurów i atrybutów specyficznych dla modułu cieniującego?

Następne pokazy Klasa aktora:

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

Klasa kontrolera modelu: class ModelController {class IShader * shader; int textureId; odcień vec4; pływak alfa; struct Vertex * vertexArray; };

Klasa Shadera zawiera tylko obiekt cieniujący, kompiluje i łączy podprogramy itp.

W klasie Game Logic faktycznie renderuję obiekt:

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

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

Zauważ, że mimo iż Actor rozszerza ISceneNode, nie zacząłem jeszcze implementować SceneGraph. Zrobię to, gdy tylko rozwiążę ten problem.

Jakieś pomysły, jak to poprawić? Powiązane wzory projektowe itp.?

questionAnswers(4)

yourAnswerToTheQuestion