Also das wäre mein Vorschlag (ist dem von Chris ähnlich):
Zuerst ein paar Basisklassen:
class Activator
{
public:
virtual void activate () = 0;
};
class Deactivator
{
public:
virtual void deactivate () = 0;
};
Von denen leitest Du für jede Möglichkeit, die Dir im Moment einfällt, eine Klasse ab. Diese registrieren sich bei einem Factory-Objekt:
class Factory
{
public:
static Activator *getActivator (const char *name);
static Deactivator *getDeactivator (const char *name);
static registerActivator (Activator *act, const char *name);
static registerDeactivator (Deactivator *deact, const char *name);
...
};
Die Shader-Basis-Klasse:
class Shader
{
public:
Shader (Activator *a, Deactivator *d)
: m_activator (a)
, m_deactivator (b)
{ }
virtual ~Shader ()
{
delete (m_activator);
delete (m_deactivator);
}
Activator *activator () { return (m_activator); }
Deactivator *deactivator () { return (m_deactivator); }
void begin ()
{
if ((m_lastActivator == 0) || (m_lastActivator != m_activator)
{
m_activator->activate ();
m_lastActivator = m_actiavator ();
}
}
void end ()
{
if ((m_lastDeactivator == 0) || (m_lastDeactivator != m_deactivator)
{
m_deactivator->activate ();
m_lastDeactivator = m_deactivator ();
}
}
private:
Activator *m_activator;
Deactivator *m_deactivator;
static Activator *m_lastActivator;
static Deactivator *m_lastDeactivator;
};
// static initializations (lives in Shader.cpp file)
Activator *Shader::m_lastActivator = 0;
Deactivator *Shader::m_lastDeactivator = 0;
Jetzt bastelst Du Dir einen Shader zusammen:
class MyShader : public Shader
{
public:
MyShader ()
: Shader (Factory::getActivator ("test"), Factory::getDeactivator ("test"))
{ }
...
};
Das letzte Problem ist jetzt, dass Du eigentlich die Shader::begin() und Shader::end() nicht implementieren kannst, wenn Du nicht weisst, welcher Shader als nächstes kommt. Aber das sollte auch kein Problem sein, wenn Du beide Funktionen in die Renderer-Klasse einbaust, die die Shader benutzt.
MfG,
Tilmann