C++ framework for multimedia software like Games
Wed Nov 09 17:07:25 CET 2011
nb comments: 0

Aujourd’hui je vais vous présenter mon premier système de font sur 3dNovac.
A l'origine j'ai utilisé ce système pour afficher tout les textes du Zappy. Autant dire que c’était moche ! mais suffisant :)

    

La Bitmap

La technique consistais donc à utiliser une bitmap pré-calculée. La voici :
 
Évidement si c'était aussi moche sur le Zappy, c’était surtout du à la mauvaise qualité de cette bitmap. Pour l’obtenir j'avais utilisé un générateur. Mais impossible de retrouver le nom.
 

  Utilisation des DisplayList

Voila, avec une aussi simple texture, pas trop de soucis pour afficher du texte. Mais au final le plus intéressant est la technique utilisée pour le rendu du texte.
Le principe étant de créer un tableau de display list avec autant de display lists que de caractères pour ensuite les enregistrer un par un dedans.

// on construit toutes les display lists
_font
->base = glGenLists(128);
for (int i = 0; TEXT_FONT[i] != '\0'; i++)

   
{

       
glNewList(_font->base + TEXT_FONT[i], GL_COMPILE);

       
DrawCaract(i);

        glEndList
();

   
}


// On draw un caractere dans la display list courant
void    gFont::DrawCaract(int posListCaract)
{
    float offsetX = ((posListCaract % NB_CARACT_X) * SIZE_TEXT_X) / SIZE_FONT_X;
    float offsetY = 1 -
((posListCaract / NB_CARACT_X) * SIZE_TEXT_Y) / SIZE_FONT_Y;

    glBindTexture(GL_TEXTURE_2D, _font->texture);
    glBegin(GL_QUADS);
        glTexCoord2f(offsetX, offsetY);
        glVertex2i(0, 1);
       
       
glTexCoord2f(OffsetX + ((SIZE_TEXT_X - 2) / SIZE_FONT_X), offsetY);

        glVertex(1, 1);

        glTexCoord2f(offsetX +
((SIZE_TEXT_X - 2) / SIZE_FONT_X), offsetY -
                     
(SIZE_TEXT_Y / SIZE_FONT_Y));
        glVertex2i(1, 0);

        glTextCoord2f(offsetX, offsetY - (SIZE_TEXT_Y / SIZE_FONT_X));
        glVertex2i(0, 0);
    glEnd();
    glTranslatef(1, 0, 0);
}

Vous pourrez remarquer que l'on créer nos 128 display lists avec la fonction "glGenLists", celle ci nous renvoi l'index de la première DisplayList.
Également, si vous ne l'avez pas encore deviné, un caractère correspondant simplement à un carre texturé. Au moment du rendu il suffira de rendre la texture transparente.
Ainsi nous n'avons plus qu'a appeler les bonnes display list en fonction de la chaîne que l'on veut écrire.

Le rendu :

void gFont::Display(const std::string &s)
{
    glEnable(GL_TETURE_2D);
    glEnable(GL_BLEND);        // pour rendre la texture transparente
    glBlendFunc(GL_SRC_ALPHA, GL_ONE);

    glPushMatrix();
    glListBase(_font->base);
    glCallLists(s.size(), GL_BYTE, s.c_str()); // le rendu des displayLists
    glPopMatrix();
   
    glDisable(GL_BLEND);
    glDisable(GL_TEXTURE_2D);    
 

}

E t voila, par magie notre text s'affiche. En fait la fonction glCallLists reçoit en paramètre un array contenant les numéros de chaque display list à rendre.
Le rendu ce fait donc automatiquement :)

Voila donc mon premier système de font, simple et efficace !

PS :
Un truc important que j'ai oublier de dire :
    Je vous ai présenté le rendu direct et indirect (displayList), mais sachez que ces méthodes de rendu sont maintenant deprecated sous OpenGL3 et +
    Je suis justement en train de porter 3dNovac sur Opengl3.3 et 4.1. Malheureusement je dois recoder une bonne partie du système de rendu. Je ferais une news sur le sujet.

Author: Ponpon
Comments
Pseudo
Add new comment:
Post
Loading...