Engine-Rendering-Pipeline: Generische Erstellung von Shadern

Ich versuche, eine 2D-Game-Engine mit OpenGL ES 2.0 (derzeit iOS) zu erstellen. Ich habe Application Layer in Objective C und einen separaten eigenständigen RendererGLES20 in C ++ geschrieben. Außerhalb des Renderers wird kein GL-spezifischer Aufruf durchgeführt. Es funktioniert perfekt.

Bei der Verwendung von Shadern treten jedoch einige Designprobleme auf. Jeder Shader hat seine eigenen Attribute und Uniformen, die unmittelbar vor dem Hauptaufruf (in diesem Fall glDrawArrays) festgelegt werden müssen. Um zum Beispiel eine Geometrie zu zeichnen, würde ich Folgendes tun:

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

Wie Sie sehen können, ist dieser Code extrem starr. Wenn ich einen anderen Shader verwenden würde, z. B. Ripple-Effekt, müsste ich zusätzliche Uniformen, Scheitelpunktattribute usw. übergeben. Mit anderen Worten, ich müsste den Render-Quellcode von RendererGLES20 ändern, um nur den neuen Shader zu integrieren.

Gibt es eine Möglichkeit, das Shader-Objekt vollständig zu generieren? Was ist, wenn ich nur das Shader-Objekt ändern und mich nicht um die Neukompilierung der Spielquelle kümmern möchte? Irgendeine Möglichkeit, den Renderer von Uniformen und Attributen usw. unabhängig zu machen. Obwohl wir Daten an Uniformen weitergeben müssen, was ist der beste Ort, um das zu tun? Modellklasse? Sind der Modellklasse Shader-spezifische Uniformen und Attribute bekannt?

Folgendes zeigt die Schauspielerklasse:

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

Modellcontrollerklasse: Klasse ModelController {Klasse IShader * Shader; int textureId; vec4 Tönung; float alpha; struct Vertex * vertexArray; };

Die Shader-Klasse enthält nur das Shader-Objekt, das Kompilieren und Verknüpfen von Unterprogrammen usw.

In der Game Logic-Klasse rendere ich das Objekt tatsächlich:

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

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

Bitte beachten Sie, dass ich mit der Implementierung von SceneGraph noch nicht begonnen habe, obwohl Actor ISceneNode erweitert. Ich werde das tun, sobald ich dieses Problem gelöst habe.

Irgendwelche Ideen, wie man das verbessern kann? Verwandte Designmuster etc?

Antworten auf die Frage(4)

Ihre Antwort auf die Frage