NeHe - Lektion 14 - Outline Fonts

Lektion 14



Diese Tutorial ist ein Nachfolger zum Vorherigen. In Tutorial 13 habe ich Ihnen beigebracht, wie man Bitmap Fonts verwendet. In diesem Tutorial bringe ich Ihnen bei, wie man 3D Fonts (Outline Fonts) verwendet.

Die Art, wie wir 3D Fonts erzeugen, ist ziemlich ähnlich zu der Art, wie wir den Bitmap Font in Lektion 13 erstellt haben. Wie dem auch sei... 3D Fonts sind 100 mal cooler! Sie können 3D Fonts in der Größe ändern, auf dem Screen in 3D bewegt werden. Keine flachen 2D Buchstaben. Mit Outline Fonts können Sie jeden installierten Font auf Ihrem Computer in 3D Fonts für OpenGL verwandeln, komplett mit den richtigen Normalenvektoren, so dass die Buchstaben schön strahlen, wenn Licht auf sie scheint.

Eine kleine Anmerkung: dieser Code ist Windows-spezifisch. Er benutzt die wgl Funktionen von Windows um den Font zu erzeugen. Dafür hat Apple aber agl, was das Selbe machen sollte und X hat glx. Unglücklicherweise kann ich Ihnen nicht garantieren, dass der Code portabel ist. Wenn irgendwer einen Plattform unabhängigen Code zum Fonts zeichnen hat, schickt ihn mir und ich werde ein anderes Font-Tutorial schreiben.

Wir fangen mit dem typischen code aus Lektion 1 an. Wir fügen den stdio.h Header für die Standard Ein-/Ausgaben hinzu, den stdarg.h Header um Text zu parsen und Variablen in Text zu verwandeln und letztendlich math.h, damit wir den Text auf dem Bildschirm bewegen können, indem wir SIN und COS verwenden.

#include <windows.h>                        // Header Datei für Windows
#include <math.h>                        // Header Datei für Windows Math Library    ( HINZUGEFÜGT )
#include <stdio.h>                        // Header Datei für Standard Input/Output    ( HINZUGEFÜGT )
#include <stdarg.h>                        // Header Datei für Variable Argument Routines    ( HINZUGEFÜGT )
#include <gl\gl.h>                        // Header Datei für die OpenGL32 Library
#include <gl\glu.h>                        // Header Datei für die GLu32 Library
#include <gl\glaux.h>                        // Header Datei für die GLaux Library

HDC        hDC=NULL;                    // Privater GDI Device Context
HGLRC        hRC=NULL;                    // Permanenter Rendering Context
HWND        hWnd=NULL;                    // Enthält unser Fenster-Handle
HINSTANCE    hInstance;                    // Enthält die Instanz der Applikation

Wir fügen 2 neue Variablen hinzu. base wird die Nummer der ersten Display Liste enthalten, die wir erzeugen. Jeder Buchstabe benötigt eine eigene Display Liste. Der Buchstabe 'A' ist 65 in der Display Liste, 'B' ist 66, 'C' ist 67, usw. Deshalb wir 'A' in der Display Liste base+65 gespeichert.

Als nächstes fügen wir eine Variable names rot hinzu. rot wird zum rotieren des Textes auf dem Screen verwendet, indem SIN und COS verwendet wird. Außerdem werden dadurch die Farben pulsieren.

GLuint    base;                            // Basis Display Liste für den Font Satz    ( HINZUGEFÜGT )
GLfloat    rot;                            // wird benutzt um den Text rotieren zu lassen    ( HINZUGEFÜGT )

bool    keys[256];                        // Array das für die Tastatur Routine verwendet wird
bool    active=TRUE;                        // Fenster Aktiv Flag standardmäßig auf TRUE gesetzt
bool    fullscreen=TRUE;                    // Fullscreen Flag ist standardmäßig auf TRUE gesetzt

GLYPHMETRICSFLOAT gmf[256] wird Informationen über die Plazierung und Orientierung für jede der 256 Display Listen enthalten. Wir wählen einen Buchstaben mittels gmf[num] aus. num ist die Nummer der Display Liste, über die wir etwas wissen möchten. Später werde ich Ihnen im Code zeigen, wir man die Breite eines jeden Buchstaben herausfindet, so dass Sie den Text automatisch auf dem Screen zentrieren können. Behalten Sie im Hinterkopf, dass jeder Buchstabe eine andere Breite haben kann. glyphmetrics wird unser Leben um ein wesentliches vereinfachen.

GLYPHMETRICSFLOAT gmf[256];                    // Speicherplatz für Informationen über unseren Font

LRESULT    CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);        // Deklaration für WndProc

Der folgende Codeabschnitt erzeugt den eigentlichen Font, auf ähnliche Weise wie wir es mit den Bitmap Font gemacht haben. Wie in Lektion 13 war das der schwierigste Codeteil.

'HFONT font' enthält unsere Windows Font ID.

Als nächstes definieren wir base. Das machen wir, indem wir eine Gruppe von 256 Display Listen mittels glGenLists(256) erzeugen. Nachdem die Display Listen erzeugt wurden, enthält base die Nummer der ersten Liste.

GLvoid BuildFont(GLvoid)                    // erzeuge unseren Bitmap Font
{
    HFONT    font;                        // Windows Font ID

    base = glGenLists(256);                    // Speicherplatz für 256 Buchstaben

Nun zum spaßigen Teil. Wir erzeugen unseren eigenen 3D Font. Wir fangen damit an, die Größe des Fonts zu spezifizieren. Sie werden bemerken, dass es eine negative Zahl ist. Indem wir ein Minus voranstellen, teilen wir Windows mit, dass uns ein Font basierend auf der BUCHSTABEN Höhe gesucht werden soll. Wenn wir eine positive Zahl verwenden, suchen wir nach einem Font basierend auf der ZELL Höhe.

    font = CreateFont(    -12,                // Höhe unseres Font 

Dann geben wir die Zell-Breite an. Sie werden bemerken, dass ich diese auf 0 gesetzt habe. Dadurch, dass Werte auf 0 gesetzt werden, wird Windows die Standardwerte verwenden. Sie können mit diesem Wert etwas rumspielen, wenn Sie wollen. Machen Sie den Font breiter, etc.

                0,                // Breite unseres Font

Der Fluchtwinkel (Angle of Escapement) rotiert den Font. Orientierungwinkel 'Orientation Angle' ist laut MSDN Hilfe der Winkel in Zehntel Grad zwischen den Buchstabens Basislinie und der X-Achse des Devices. Leider habe ich keine Idee, was das bedeuet :(

                0,                // Angle Of Escapement
                0,                // Orientation Angle

Font Weight ist ein großartiger Parameter, mit dem man die Dicke des Fonts einstellen kann. Sie können ein Zahl zwischen 0 und 1000 verwenden oder Sie benutzen eine der vordefinierten Werte. FW_DONTCARE ist gleich 0, FW_NORMAL ist 400, FW_BOLD ist 700 und FW_BLACK entspricht 900. Es gibt noch viel mehr vordefinierte Werte, aber diese 4 geben eine gute Übersicht. Je höher der Wert, um so dicker der Font.

                FW_BOLD,            // Font Dicke

Italic (kursiv), Underline (unterstrichen) und Strikeout (durchgestrichen) können entweder TRUE oder FALSE sein. Wenn Underline also auf TRUE gesetzt wird, wird der FONT unterstrichen. Wenn es gleich FALSE ist, dann nicht. Ziemlich einfach :)

                FALSE,                // Italic
                FALSE,                // Underline
                FALSE,                // Strikeout

'Character set Identifier' beschreibt die Art der Buchstaben, die Sie verwenden wollen. Es gibt zu viele Arten, um diese hier zu erklären. CHINESEBIG5_CHARSET (chinesisch), GREEK_CHARSET (griechisch), RUSSIAN_CHARSET (russisch), DEFAULT_CHARSET (standard), etc. ANSI ist das was ich benutze, obwohl DEFAULT wohl genau so gut arbeiten würde.

Wenn Sie Fonts wie Webdings oder Wingdings verwenden wollen, müssen Sie SYMBOL_CHARSET anstatt von ANSI_CHARSET verwenden.

                ANSI_CHARSET,            // Character Set Identifier

Die Ausgabe Genauigkeit (Output Precision) ist sehr wichtig. Sie teilt Windows die Art des Zeichensatz mit, der verwendet werden soll, wenn mehr als eine Art verfügbar ist. OUT_TT_PRECIS teilt Windows mit, dass, für den Fall das es mehr als eine Font-Art mit dem entsprechenden Namen zu wählen ist, die TRUETYPE Version des Fonts gewählt werden soll. Truetype Fonts sehen immer besser aus, insbesondere wenn Sie sie groß machen. Sie können auch OUT_TT_ONLY_PRECIS verwenden, was IMMER versucht TRUETYPE Fonts zu verwenden.

                OUT_TT_PRECIS,            // Output Precision

Clipping Precision (Abschneide-Genauigkeit) ist die Art des Abschneidens, die vorgenommen werden soll, wenn der Font sich außerhalb der Clipping Region befindet. Es gibt nicht viel dazu zu sagen, lassen Sie es einfach beim Standard-Wert.

                CLIP_DEFAULT_PRECIS,        // Clipping Precision

Die Ausgabe Qualität ist sehr wichtig. Sie können folgende benutzen: PROOF, DRAFT, NONANTIALIASED, DEFAULT oder ANTIALIASED. Wir alle wissen, dass antialiased Fonts gut aussehen:) Eine Font zu Antialiasen ist der selbe Effekt als wenn Sie Smoothing in Windows einschalten. Es lässt alles weniger kantig aussehen.

                ANTIALIASED_QUALITY,        // Ausgabe Qualität

Als nächstes haben wir Familie und Pitch Eigenschaften. Für Pitch können Sie die Werte DEFAULT_PITCH, FIXED_PITCH und VARIABLE_PITCH haben und für Familie FF_DECORATIVE, FF_MODERN, FF_ROMAN, FF_SCRIPT, FF_SWISS, FF_DONTCARE. Spielen Sie etwas mit diesen Werten herum, um herauszufinden, was diese bewirken. Ich setze beide auf die Standardwerte.

                FF_DONTCARE|DEFAULT_PITCH,    // Familie und Pitch

Schließlich... haben wir den Namen des Fonts. Starten Sie Microsoft Word oder einen anderen Texteditor. Schauen Sie sich die Schriftarten an und suchen Sie sich einen aus, der Ihnen gefällt. Um den entsprechenden Font zu nutzen, ersetzen Sie 'Comic Sans MS' mit dem Namen des Fonts, den Sie ausgewählt haben.

                "Comic Sans MS");        // Font Name

Nun wählen wir den Font aus und verbinden ihn mit unserem DC.

    SelectObject(hDC, font);                // wähle den erzeugten Font aus

Nun zu dem neuen Code. Wir erzeugen unseren Outline Font mit dem Befehl wglUseFontOutlines. Wir wählen unseren DC, den Anfangsbuchstaben, die Anzahl der zu erzeugenden Buchstaben, den 'base' Display Listen Wert. Alles sehr ähnlich zu dem Vorgehen bei Bitmap Fonts.

    wglUseFontOutlines(    hDC,                // wähle aktuellen DC
                0,                // Anfangsbuchstaben
                255,                // Anzahl der zu erzeugenden Display Listen
                base,                // Start Display List

Das ist aber noch nicht alles. Wir setzen dann noch das 'deviation level' (Abweichungs-Level). Je näher dieses an 0.0f ist, desto weicher wird der Font aussehen. Nachdem wir das gesetzt haben, setzen wir die Tiefe des Font. Dies beschreibt, wie dick der Font auf der Z-Achse sein soll. 0.0f erzeugt einen einfach aussehenden 2D Font und 1.0f erzeugt einen Font mit etwas Tiefe.

Der Parameter WGL_FONT_POLYGONS teilt OpenGL mit, dass ein solider Font aus Polygonen erzeugt werden soll. Wenn wir statt dessen WGL_FONT_LINES verwenden würden, wäre der Font ein Drahtgittermodell (aus Linien gemacht). Es ist auch wichtig darauf hinzuweisen, dass, wenn Sie GL_FONT_LINES verwenden, keine Normalenvektoren erzeugt werden, so dass eine Beleuchtung nicht korrekt funktionieren würde.

Der letzte Parameter gmf zeigt auf die Adresse des Buffers für die Display Listen Daten.

                0.0f,                // Abweichung des wahren Umrisses
                0.2f,                // Font Tiefe auf der Z-Ebene
                WGL_FONT_POLYGONS,        // benutze Polygone, keine Linien
                gmf);                // Addresse des Buffer der die Daten empfängt
}

Der folgende Code ist ziemlich einfach. Er löscht die 256 Display Listen aus dem Speicher, beginnend mit der ersten Liste, die durch 'base' spezifiziert ist. Ich bin mir nicht sicher, ob Windows das für Sie machen würde, aber es besser auf der sicheren Seite zu stehen, als das Nachsehen zu haben :)

GLvoid KillFont(GLvoid)                        // Lösche den Font
{
     glDeleteLists(base, 256);                // Lösche alle 256 Zeichen 
}

Nun zur meiner kleinen handlichen GL Text Routine. Sie rufen diesen Codeabschnit mit dem Befehl glPrint("hier ihr Text") auf. Genau auf die selbe Weise, wie in Lektion 13 wo Sie Bitmap Fonts auf den Screen zeichnen. Der Text ist in dem String *fmt gespeichert.

GLvoid glPrint(const char *fmt, ...)                // eigene GL "Print" Routine
{

Die erste folgende Zeile erzeugt eine Variable namens length. Wir werden diese Variable dazu benutzen, um herauszufinden, wie lang unser Text ist. Die zweite Zeile erzeugt Speicherplatz für ein 256 Zeichen langen String. text ist der String, den wir auf den Screen bringen werden. Die dritte Zeile erzeugt einen Pointer der auf die Argumenten-Liste zeigt, die wir mit dem String übergeben. Wenn wir irgendwelche Variablen mit dem Text übergeben haben, zeigt dieser Zeiger auf diese.

    float        length=0;                // wird benutzt um die Länge des Textes herauszufinden
    char        text[256];                // enthält unseren String
    va_list        ap;                    // Zeiger auf die Argumenten-Liste

Die nächsten beiden Codezeilen überprüfen, ob es etwas zum anzeigen gibt. Wenn es keinen Text gibt, ist fmt gleich nichts (NULL) und nichts wird auf dem Screen gezeichnet.

    if (fmt == NULL)                    // wenn kein Text vorhanden ist
        return;                        // mache nichts

Die folgenden drei Zeilen Code konvertieren jegliche Symbole aus dem Text in die eigentlichen Zahlen, die das Symbol repräsentiert. Der endgültige Text und alle konvertierten Symbole werden in dem String namens 'text' abgespeichert. Ich erkläre Symbole weiter unter noch detaillierter.

    va_start(ap, fmt);                    // Parse den String für Variablen
        vsprintf(text, fmt, ap);                // und konvertiere Symbole in Zahlen
    va_end(ap);                        // Ergebnisse werden in text gespeichert

Danke an Jim Williams, der den folgenden Code vorgeschlagen hat. Ich habe den Text manuell zentriert. Seine Methode funktioniert wesentlich besser :)

Wir fangen mit einer Schleife an, die durch den gesamten Text geht, Buchstabe für Buchstabe. strlen(text) liefert uns die Länge des Textes. Nachdem wir die Schleife initialisiert haben, inkrementieren wir den Wert von Length um die Breite (width) jedes Buchstabens. Wenn wir das getan haben, wird der Wert, der in length gespeichert ist, die Breite unseres gesamten Strings sein. Wenn wir also "hello" ausgeben und wenn wir Dusel haben und jeder Buchstabe exakt 10 Einheiten breit ist, erhöhen wir den Wert in lenght um die Breite des ersten Buchstabens, also 10. Danach überprüfen wir die Breite des zweiten Buchstaben. Die Breite wäre ebenfalls 10, weshalb length gleich 10+10 (20) wäre. Wenn wir mit allen 5 Buchstaben durch sind, erhalten wir für length einen Wert von 50 (5*10).

Der Code, der uns die Breite eines jeden Buchstabens liefert ist gmf[text[loop]].gmfCellIncX. Erinnern Sie sich daran, dass gmx die Informationen über jede Display Liste speichert. Wenn loop gleich 0 ist, ist text[loop] unser erster Buchstabe in unserem String. Wenn loop gleich 1 ist, ist text[loop] der zweite Buchstabe in unserem String. gmfCellIncX teilt uns mit wie Breit der ausgewählte Buchstabe ist. gmfCellIncX ist eigentlich die Distanz, um die man sich nach rechts bewegt, nachdem der Buchstabe gezeichnet wurde, damit die Buchstaben nicht übereinander gezeichnet werden. Deshalb ist die Distanz auch gleichzeitig unsere Breite :) Sie können auch die Buchstabenhöhe herausfinden, indem Sie den gmfCellIncY Befehl verwenden. Das mag nützlich sein, wenn Sie den Text vertikal und nicht mehr horizontal zeichnen wollen.

ANMERKUNG: Curt Werline fügt hinzu - Wenn Sie die Dimensionen des Text-Strings berechnen, benutzen Sie gmfCellIncX für die Breite und nehmen gmfCellIncY für die Höhe an. Diese Werte sind Offsets und keine wahren Dimensionen. Um die wirklichen Dimensionen zu erhalten, sollten Sie gmfBlackBoxX und gmfBlackBoxY verwenden.

    for (unsigned int loop=0;loop<(strlen(text));loop++)    // Schleife um die Text-Länge herauszufinden
    {
        length+=gmf[text[loop]].gmfCellIncX;        // Inkrementiere Length um die Breite jedes Buchstabens
    }

Letzlich nehmen wir die Länge, die wir berechnet haben und machen daraus eine negative Zahl (da wir uns nach links vom Zentrum aus bewegen müssen, um unseren Text zu zentrieren). Dann dividieren wir die Länge durch 2. Wir wollen nicht den gesamten Text links vom Zentrum haben, nur die Hälfte des Textes!

    glTranslatef(-length/2,0.0f,0.0f);            // zentriere unseren Text auf dem Screen

Wir pushen dann GL_LIST_BIT, das verhindert, dass glListBase andere Display Listen, die wir vielleicht in unserem Programm verwenden, beeinflusst werden.

Der Befehl glListBase(base) teilt OpenGL mit, wo die richtige Display Liste für den jeweiligen Buchstaben zu finden ist.

    glPushAttrib(GL_LIST_BIT);                // Pusht die Display Listen Bits
    glListBase(base);                    // Setze den Basis Buchstaben auf 0

Nun, da OpenGL weiß, wo die Buchstaben liegen, können wir OpenGL mitteilen, dass es den Text auf den Screen schreiben soll. glCallLists schreibt den gesamten Text-String auf einmal auf den Screen, indem mehrere Display Listen aufgerufen werden.

Die Zeile macht folgendes: als erstes teilen wir OpenGL mit, dass wir Display Listen auf den Screen brignen. strlen(text) findet heraus, wieviele Buchstaben wir auf den Bildschirm bringen. Als nächstes müssen wir wissen, welches die größte Listennummer ist, die wir senden werden. Wir werden immer noch nicht mehr als 255 Buchstaben senden. Deshalb können wir UNSIGNED_BYTE verwenden. (ein Byte repräsentiert eine Zahl zwischen 0 und 255 was genau das ist, was wir brauchen). Letzendlich sagen wir noch, was wir angezeigt haben wollen, indem wir den Text übergeben.

Für den Fall das Sie sich wundern, warum die Buchstaben nicht zusammenstossen. Jede Display Liste für jeden Buchstaben weiß, wo die rechte Seite des Buchstaben ist. Nachdem der Buchstabe gezeichnet wurde, translatiert OpenGL zur rechten Seite des gezeichneten Buchstabens. Der nächste Buchstabe oder das nächste Objekte, dass gezeichnet wird, wird an dem Ort gezeichnet, zu dem OpenGL zu letzt translatiert hat, in diesem Falle also recht von dem zuletzt gezeichneten.

Letztendlich poppen wir GL_LIST_BIT setzen GL so zurück, wie es vorher war, bevor wir unsere Basis Einstellung mittels glListBase(base) setzen.

    glCallLists(strlen(text), GL_UNSIGNED_BYTE, text);    // zeichnet den Display Listen Text
    glPopAttrib();                        // Poppt die Display Listen Bits
}

Der Resizing Code ist genau der selbe Code wie in Lektion 1, weshalb wir ihn überspringen.

Es gibt ein paar neue Zeilen am Ende des InitGL Codes. Die Zeile BuildFont() aus Lektion 13 ist immer noch da, zusammen mit neuem Code für schnelle und dreckige Beleuchtung. Light0 ist auf den meisten Grafikkarten vordefiniertn und leuchtet die Szene nett aus, ohne Anstrengungen meinerseits :)

Ich habe ebenfalls den Befehl glEnable(GL_Color_Material) hinzugefügt. Da die Buchstaben 3D Objekte sind, müssen Sie Materialfärbung aktivieren, ansonsten beeinflusst ein ändern der Farbe mit glColor3f(r,g,b) nicht die Farbe des Textes. Wenn Sie Formen auf Ihrem Screen zeichnen, während Sie Text ausgeben, aktivieren Sie Materialfärbung bevor Sie Text ausgeben und deaktivieren Sie es nachdem Sie den Text gezeichnet haben, da alle anderen Objekte auch gefärbt werden.

int InitGL(GLvoid)                        // Der ganze Setup Kram für OpenGL kommt hier rein
{
    glShadeModel(GL_SMOOTH);                // aktiviere Smooth Shading
    glClearColor(0.0f, 0.0f, 0.0f, 0.5f);            // Schwarzer Hintergrund
    glClearDepth(1.0f);                    // Depth Buffer Setup
    glEnable(GL_DEPTH_TEST);                // aktiviert Depth Testing
    glDepthFunc(GL_LEQUAL);                    // Die Art des auszuführenden Depth Test
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);    // wirklich nette Perspektiven Berechnungen
    glEnable(GL_LIGHT0);                    // aktiviert Standard-Licht (schnell und dreckig) ( NEU )
    glEnable(GL_LIGHTING);                    // aktiviert Beleuchtung            ( NEU )
    glEnable(GL_COLOR_MATERIAL);                // aktiviert Materialfärbung            ( NEU )

    BuildFont();                        // erzeuge den Font                ( HINZUGEFÜGT )

    return TRUE;                        // Initialisierung war OK
}

Nun zum Zeichnen-Code. Wir fangen mit dem löschen des Screens und des Depth Buffers an. Wir rufen glLoadIdentity() auf, um alles zu resetten. Dann gehen wir zehn Einheiten in den Screen hinein. 3D Fonts sehen großartig im Perspektiven Modus aus. Je tiefer Sie sich in den Screen hinein bewegen, desto kleiner wird der Font. Je näher ran Sie kommen, desto größer wird der Font.

3D Fonts können auch mit glScalef(x,y,z) manipuliert werden. Wenn Sie den Font um das 2fache größer haben wollen, benutzen Sie glScalef(1.0f,2.0f,1.0f). Die 2.0f ist auf der Y-Achse, was OpenGL mitteilt, die Liste zwei mal so groß zu zeichnen. Wenn die 2.0f auf der X-Achse wäre, wäre der Buchstabe doppelt so dick.

int DrawGLScene(GLvoid)                        // Hier kommt der ganze Zeichnen-Kram hin
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);    // Lösche den Bildschirm und den Depth-Buffer
    glLoadIdentity();                    // Resette die View
    glTranslatef(0.0f,0.0f,-10.0f);                // bewege zehn Einheiten in den Screen hinein

Nachdem wir uns in den Screen hinein bewegt haben, wollen wir den Text rotieren lassen. Die nächsten 3 Zeilen lassen den Screen auf allen drei Achsen rotieren. Ich multipliziere rot mit verschiedenen Zahlen, damit jede Rotation eine andere Geschwindigketi erhält.

    glRotatef(rot,1.0f,0.0f,0.0f);                // Rotiere auf der X-Achse
    glRotatef(rot*1.5f,0.0f,1.0f,0.0f);            // Rotiere auf der Y-Achse
    glRotatef(rot*1.4f,0.0f,0.0f,1.0f);            // Rotiere auf der Z-Achse

Nun zu den verrückten Farben. Wie immer mache ich gebrauch von der Variable, die hochgezählt wird (rot). Die Farbe pulsiert hoch und runter, indem wir COS und SIN verwenden. Ich dividiere den Wert von rot durch verschiedene Zahlen, so dass jede Farbe nicht in der selben Geschwindigkeit erhöht wird. Das endgültige Ergebniss ist ganz nett.

    // pulsierende Farben basierend auf der Rotation
    glColor3f(1.0f*float(cos(rot/20.0f)),1.0f*float(sin(rot/25.0f)),1.0f-0.5f*float(cos(rot/17.0f)));

Nun zu meinem Lieblinspart... Den eigentlich Text auf den Screen bringen. Ich benutze den selben Befehl den wir auch für die Bitmap Fonts verwendet haben. Alles was Sie machen müssen, um Text auf den Screen zu bekommen ist glPrint ("{den Text den Sie wollen}") benutzen. So einfach ist das!

Im folgenden Code geben wir 'NeHe' aus, ein Leerzeichen, ein Spiegelstrich, ein Leerzeichen und die die Nummer, die in rot gespeichert ist dividiert durch 50 (um den Zähler etwas zu verlangsamen). Wenn die Zahl größer als 999.99 ist, wird die 4te Ziffer zur Linken abgeschnitten (wir wollen nur drei Ziffern links vom Dezimaltrenner haben). Nur 2 Ziffern werden nach dem Dezimaltrennzeichen angezeigt.

     glPrint("NeHe - %3.2f",rot/50);                // gebe GL Text auf dem Screen aus

Dann inkrementieren wir die Rotations Varialbe, soe dass die Farben pulsieren und der Text rotiert.

    rot+=0.5f;                        // inkrementiere die Rotations Variable
    return TRUE;                        // alles war OK
}

Als letztes muss noch KillFont() am Ende unserer KillGLWindow() eingefügt werden, ungefähr so, wie ich es unten stehen habe. Es ist wichtig, diese Zeile einzufügen. Sie räumt noch etwas auf, bevor wir das Programm beenden.

    if (!UnregisterClass("OpenGL",hInstance))        // Können wir die Klasse de-registrieren?
    {
        MessageBox(NULL,"Could Not Unregister Class.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
        hInstance=NULL;                    // Setze hInstance auf NULL
    }

    KillFont();                        // zerstöre Font
}

Am Ende dieses Tutorials sollten Sie in der Lage sein 3D Fonts in Ihren eigenen OpenGL Projekten zu verwenden. Wie in Lektion 13 habe ich das Internet nach ähnlichen Tutorials durchsucht und habe nichts gefunden. Könnte meine Seite die erste sein, die dieses Thema abdeckt und alles in einfachen C-Code erklärt? Genießt das Tutorial und happy Coding!

Jeff Molofee (NeHe)

* DOWNLOAD Visual C++ Code für diese Lektion.

* DOWNLOAD Borland C++ Builder 6 Code für diese Lektion. ( Conversion by Christian Kindahl )
* DOWNLOAD Code Warrior 5.3 Code für diese Lektion. ( Conversion by Scott Lupton )
* DOWNLOAD Delphi Code für diese Lektion. ( Conversion by Michal Tucek )
* DOWNLOAD Dev C++ Code für diese Lektion. ( Conversion by Dan )
* DOWNLOAD Euphoria Code für diese Lektion. ( Conversion by Evan Marshall )
* DOWNLOAD Game GLUT Code für diese Lektion. ( Conversion by Milikas Anastasios )
* DOWNLOAD Java Code für diese Lektion. ( Conversion by Jeff Kirby )
* DOWNLOAD JoGL Code für diese Lektion. ( Conversion by Pepijn Van Eeckhoudt )
* DOWNLOAD LCC Win32 Code für diese Lektion. ( Conversion by Robert Wishlaw )
* DOWNLOAD Mac OS Code für diese Lektion. ( Conversion by Anthony Parker )
* DOWNLOAD MASM Code für diese Lektion. ( Conversion by Greg Helps )
* DOWNLOAD Pelles C Code für diese Lektion. ( Conversion by Pelle Orinius )
* DOWNLOAD Visual Basic Code für diese Lektion. ( Conversion by Ross Dawson )
* DOWNLOAD Visual Basic Code für diese Lektion. ( Conversion by Edo )
* DOWNLOAD Visual Studio .NET Code für diese Lektion. ( Conversion by Grant James )



Deutsche Übersetzung: Joachim Rohde
Der original Text ist hier zu finden.
Die original OpenGL Tutorials stammen von NeHe's Seite.