Ich versuche, eine 2D-Spiel-Engine mit OpenGL ES 2.0 (iOS für jetzt) zu erstellen. Ich habe Application Layer in Objective C und ein separates eigenständiges RendererGLES20 in C ++ geschrieben. Außerhalb des Renderers wird kein GL-spezifischer Aufruf getätigt. Es funktioniert perfekt.
Aber ich habe einige Designprobleme bei der Verwendung von Shadern. Jeder Shader hat seine eigenen Attribute und Uniformen, die unmittelbar vor dem Hauptzeichnungsaufruf festgelegt werden müssen (in diesem Fall glDrawArrays). Zum Beispiel würde ich Folgendes tun, um eine Geometrie zu zeichnen:
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, beispielsweise einen Ripple-Effekt, müsste ich zusätzliche Uniformen, Vertex-Attribute usw. übergeben. Mit anderen Worten, ich müsste den RendererGLES20-Render-Quellcode ändern, um den neuen Shader zu integrieren.
Gibt es eine Möglichkeit, das Shader-Objekt vollständig generisch zu gestalten? Was ist, wenn ich nur das Shader-Objekt ändern möchte und mir keine Sorgen über das Neukompilieren der Spielquelle machen möchte? Gibt es eine Möglichkeit, den Renderer von Uniformen und Attributen usw. unabhängig zu machen? Auch wenn wir Daten an Uniformen weitergeben müssen, was ist der beste Ort, um dies zu tun? Modellklasse? Ist der Modellklasse Shader-spezifische Uniformen und Attribute bekannt?
Folgendes zeigt Schauspielerklasse:
class Actor : public ISceneNode
{
ModelController * model;
AIController * AI;
};
Modellcontroller-Klasse: Klasse ModelController {Klasse IShader * Shader; int textureId; vec4 Farbton; float alpha; struct Vertex * vertexArray; };
Die Shader-Klasse enthält nur das Shader-Objekt, das Kompilieren und Verknüpfen von Unterroutinen 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, obwohl Actor ISceneNode erweitert, noch nicht mit der Implementierung von SceneGraph begonnen habe. Ich werde das tun, sobald ich dieses Problem behoben habe.
Irgendwelche Ideen, wie man das verbessern kann? Verwandte Designmuster etc?
Vielen Dank für das Lesen der Frage.