EuaconLabs Blogs Batched Updates
Batched Updates 25.07.2014 - 18:30 0

So hier bin ich wieder, wenn auch diesmal mit einer etwas kleineren Neuerung, die allerdings - wie ich finde - ebenfalls erwähnenswert ist. Zu erst einmal möchte die Problematik beschreiben:

 

Stellen wir uns mal vor, wir hätten ein GameObject, welches ein Sprite rendern möchte, dazu noch ein Licht, etc. etc... Wir haben dazu noch ein zweites GameObject welches ebenfalls ein Sprite hat. Unsere GameObject-Klasse besitzt unter anderem folgende Methoden:

class GameObject
{
public:

    // [...]
    void Update(const vxF32 delta);
    void Render();
};

Wir würden also zum Rendern eines GameObjects lediglich die Render()-Funktion aufrufen, und das wär's dann. Allerdings ist das eine ziemlich schlechte Implementierung. Für kleine Spiele mag sie durchaus durch ihre einfache Umsetzung überzeugen, aber ich habe mich für etwas fortgeschritteneres entschieden. Für das sogenannte Batched Updating.

 

So, jetzt habe ich mit einem Begriff um mich geschmissen, und ihr dürft jetzt alle schön raten, was ich damit meine. Nein, ganz so fies bin ich dann doch nicht, ich erkläre es euch. Unter Batched Updating versteht man das Updaten eines Subsystems der Engine in einem Zug. In unserem Beispiel würden wir ein GameObject rendern, dann würden wir irgendetwas anderes machen, dann würden wir wieder ein GameObject rendern, und dann wieder irgendetwas anderes machen. Das ist unpraktisch, da es unter dem Strich dafür sorgt, dass viele Optimierungen schlichtweg sehr schwer bis unmöglich zu implementieren sind. Ein gutes Beispiel hierfür ist zum Beispiel das Sortieren nach einem Material. Hätten wir unsere Objekte, wie es durchaus üblich ist, in einem Szenen-Graphen gekapselt, dann hätten wir keine Chance, Objekte mit gleicher Textur für ihr zugehöriges Sprite in einem Block zu rendern. Wir würden die ganze Zeit die Texturen wechseln müssen, was bei zu häufiger Anwendung durchaus langsam sein kann. Wie können wir also das Rendering komplett verlegen? Ganz einfach: Wir rendern einfach gar nichts! Nein, ganz so nun auch wieder nicht, aber unsere GameObjects haben einfach keine Render()-Methode mehr. Vielmehr erstellen wir eine Singleton-Klasse, welche eine Liste aller Objekte enthält, die gerendert werden sollen. Diese Objekte besitzen dann Methoden, die benötigte Daten bereitstellen und mit denen sie sich selbst zeichnen können. Außerdem besitzen sie auch eine Eigenschaft namens visible (oder so ähnlich) über die wir der Rendering-Engine mitteilen können, ob das Objekt überhaupt gezeichnet werden soll. Unser GameObject bestitzt dann lediglich die Möglichkeit, die Eigenschaften dieses zeichenbaren Objektes zu verändern, und so die Rendering-Phase zu beeinflussen. So können wir zum Beispiel über den Szenen-Graphen iterieren, und einfach sämtliche GameObjects mit Sprites, die sowieso nicht zu sehen sein würden einfach auf unsichtbar stellen, und so gar nicht erst zeichnen lassen. In unserem Main-Loop können wir dann einfach eine Methode aufrufen, die alles zu zeichnende zeichnet, und zwar an einem Stück:

// Pseudo-Code:
while(Game.IsRunning())
{
    // Update all GameObjects:
    world.UpdateAll();
    // [...]
    // Render everything and present the result on-screen:
    RenderSystem::Get()->RenderAndSwapBuffers();
    // [...]
}

Das kann nun durchaus effizient ausgeführt werden, da unser Rendering-System nun die Objekte nach Belieben sortieren kann. Es liegt voll und ganz bei ihm. Das heißt im Endeffekt, wir müssen nur anmelden, dass wir etwas zeichnen wollen, und der Rest geschieht automatisch. Wir sagen dann lediglich, wie genau gezeichnet werden soll. Typische Eigenschaften, die wir beeinflussen, sind um Beispiel Transformationen (Position, Rotation, und Skalierung), und Texturen, sowie die visible-Eigenschaft.

Ich hoffe ihr könnt nachvollziehen, was ich eigentlich sagen wollte. Bis dahin: Macht's gut!

~ EuadeLuxe / EuaconLabs ~


Grund: