2009-03-27 5 views
3

Ich schreibe einen Text-Renderer für eine OpenGL-Anwendung. Größe, Farbe, Schriftart und Anti-Aliasing können zur Laufzeit geändert werden (und so können mehrere Schriftarten gleichzeitig auf dem Bildschirm angezeigt werden). Es gibt zu viele Kombinationen, um jeder Kombination aus String und Attributen eine Textur zuzuordnen. Es wird jedoch immer nur eine kleine Teilmenge der gesamten String-Datenbank auf dem Bildschirm angezeigt.Wie kann ich eine Cache-Textur in OpenGL verwalten?

Dies führt mich in die Möglichkeit, einen Cache für die Zeichenfolgen zu erstellen, die Rahmen für Rahmen gedruckt werden. Es wurde vorgeschrieben, dass ich nur eine Textur für die gesamte Operation verwende, da das Erstellen eines Caches mit vielen Texturen eine Textur-Swapping-Strafe für jede andere aus dem Cache gedruckte Zeichenfolge nach sich ziehen würde.

So habe ich vor mir eine 2048x2048 Textur, in die ich alle Strings platzieren kann, die ich anpassen kann, wie sie von der Anwendung für Caching-Zwecke angefordert werden. Ich habe schnell erkannt, dass es nicht trivial ist, den verfügbaren freien Speicherplatz in einem zweidimensionalen Raum zu verfolgen.

Ich habe Dinge wie Best Fit und Next Fit angeschaut, aber diese scheinen für 1d Räume geeignet zu sein.

Wie kann ich diese Cache-Textur in OpenGL verwalten?

Edit: Ich habe seit dem gelernt, dass dies eine Instanz eines "2d Verpackungsproblems" ist.

Antwort

0

Ich habe mich für einen einfachen Ansatz entschieden. Teilen Sie die Textur in Zeilen mit variabler Höhe ein. Die erste Textur, die in einer Reihe platziert wird, entscheidet über die Höhe der Reihe. Wenn eine Textur nach Höhe in eine vorhandene Zeile passen kann, prüfen Sie, ob noch genügend Breite vorhanden ist, und platzieren Sie sie dort. Ansonsten starte eine neue Zeile. Wenn eine neue Zeile nicht gestartet werden kann, speichern Sie die Zeichenfolge nicht zwischen.

2

Was Sie haben, ist das bin-Verpackungsproblem.

Schlechte Nachrichten zuerst: Es ist NP-schwer, so dass es sich lohnt, die optimale Lösung zu finden.

Ich habe solche Textur-Caching für Schriftarten auch getan. Ich habe nicht ganze Wörter zwischengespeichert, sondern nur die Glyphbilder. Das macht die Dinge viel einfacher, weil alle Ihre Bilder ungefähr quadratisch sind. Ein einfacher Grid-basierter Ansatz zur Verfolgung des Textur-Gedächtnisses funktionierte ziemlich gut.

Für den Fall, dass ich Glyphen habe, die größer als eine meiner Grid-Boxen sind, habe ich einfach zwei oder mehrere Boxen mit Brute-Force-Suche zugewiesen (es ist nicht oft passiert). Falls ich keinen passenden Block gefunden habe, habe ich zufällig einige Glyphen aus dem Cache entfernt, um freien Platz zu schaffen.

Das war viel einfacher als Dinge in einem zuletzt verwendeten Cache zu halten und fast genauso gut zu funktionieren.

Btw - Sie werden immer etwas Verschwendung von Textur-Speicher für solch einen Cache haben. Es sei denn, du bist sehr knapp im Speicher, sollte kein Problem sein. Sie sollten ein kleines Textur-Format verwenden (8-Bit Alpha funktioniert gut für Schriften).

Auch: Wenn Sie Ihre Grid-Blöcke ein Vielfaches von 8 Pixeln machen, und Sie können Ihre Antialiasing auf 4 Bits lassen Sie die Glyphen in einem der komprimierten DXT oder S3TC Formate im laufenden Betrieb komprimieren. Der verschwendete Texturraum wird auf diese Weise zu einem Nicht-Problem.

1

Wenn Sie wenig Texturspeicher haben, können Sie sich die Schriftart "Distance Field" oder "Signed Distance Field" ansehen. Sie könnten 512x512 Textur pro Schriftfamilie verwenden und Sie könnten perfekt antialiased Text jeder Größe darstellen.

Für diesen Algorithmus müssen Sie eine spezielle Textur generieren, die den Abstand vom Texel zum Rand der Textur enthält. Werfen Sie einen Blick auf Original-Papier von Valve Jungs: http://www.valvesoftware.com/publications/2007/SIGGRAPH2007_AlphaTestedMagnification.pdf. Es gibt einige Frameworks, die dies nutzen. Zum Beispiel verwendet die neueste Version von Qt ein vorzeichenbehaftetes Distanzfeld für das Text-Rendering.

+0

Oh, ich hätte das Datum vor der Veröffentlichung überprüfen sollen :) –

+0

Für eine vollständige Implementierung möchten Sie vielleicht libcinder betrachten. –

Verwandte Themen