Effect Pools im XNA Framework

15.07.2009 15:35

In der Regel verwenden Computerspiele unzählige Effekte. Dabei besitzen fast alle Effekte mindestens eine Hand voll gleicher Parameter (globale Variablen). Ein gutes Beispiel sind die Sicht- und Projektionsmatrizen. Die Anwendung muss nun für jeden Effekt dieselben Daten immer und immer wieder zuweisen.
Dem Problem begegnet man mit sog. Effect Pools. Alle Effekte die einem Effect Pool angehören können auf gemeinsam verwendete Variablen zugreifen. Als Konsequenz muss man nur noch einem Effekt die entsprechenden Parameter-Werte zuweisen und alle anderen Effekte übernehmen die Daten ebenfalls. Wenn man nun die Effekte über die Content Pipeline lädt, dann gehören diese automatisch einem statischen Effect Pool an. Gemeinsam verwendete Variablen kennzeichnen Sie in der Effekt-Datei mit dem Modifier shared.
shared float3 LightPosition = 0.0f;
Per Default gehören alle Effekte, die Sie über die Content Pipeline laden also demselben Effect Pool an. Wie aber können Effekte unterschiedlichen Effect Pools zugewiesen werden? Wirft man einen Blick auf die Konstruktorüberladungen der Effect-Klasse, dann wird man eine Signatur finden, die eine GraphicsDevice-Instanz, den kompilierten Effekt-Code, Compiler-Optionen und einen Effect Pool entgegen nimmt. Jetzt gilt es nur noch den Code des kompilierten Effekts zu ermitteln. Hierfür wird ein neuer Content Processor entwickelt, der das Resultat des Effect Importers entgegen nimmt, den Effekt kompiliert und den Code als byte-Array zurückgibt.
[ContentProcessor(DisplayName = "Plain Effect Processor")]
public class PlainEffectProcessor : ContentProcessor
{
  public override byte[] Process(
    EffectContent input, ContentProcessorContext context)
  {
    CompiledEffect oEffect = context.Convert(
      input, "EffectProcessor");
    return oEffect.GetEffectCode();
  }
}
Zur Laufzeit laden Sie das byte-Array und erzeugen eine neue Effect-Instanz:
m_oEffectPool = new EffectPool();

byte[] oCompiledEffect = this.Content.Load("Effect1");
m_oEffect1 = new Effect(this.GraphicsDevice, oCompiledEffect, CompilerOptions.None, m_oEffectPool);
 
© 2009 Jens Konerow