2012-01-13 3 views
27

Non ho opzioni per usare altro che i metodi opengl (che è glxxx() methods()). Ho bisogno di disegnare il testo usando solo i metodi gl. Dopo aver letto il libro rosso capisco che è possibile solo attraverso il metodo glBitmap(). Se questo è l'unico modo possibile, allora qualcuno può aiutarmi con le informazioni sull'array di pixel per tutti i personaggi. C'è un altro modo per disegnare del testo?Come disegnare il testo usando solo i metodi OpenGL?

risposta

5

This article descrive come eseguire il rendering di testo in OpenGL utilizzando varie tecniche.

Con solo usando OpenGL, ci sono diversi modi:

  • utilizzando glBitmap
  • utilizzando texture
  • usando liste di visualizzazione
7

Disegno testo in OpenGL normale non è uno straigth- compito in avanti. Probabilmente dovresti dare un'occhiata alle librerie per farlo (usando una libreria o un'implementazione di esempio).

Alcuni buoni punti di partenza potrebbero essere GLFont, OpenGL Font Survey e NeHe Tutorial for Bitmap Fonts (Windows).

Nota che le bitmap non sono l'unico modo per ottenere testo in OpenGL come menzionato nel sondaggio sui font.

+0

grazie per Nehe collegamento esercitazione – befzz

1

Penso che la soluzione migliore per disegnare il testo in OpenGL sia il font texture, lavoro con loro per molto tempo. Sono flessibili, veloci e di bell'aspetto (con alcune eccezioni posteriori). Uso un programma speciale per convertire i file di font (.ttf ad esempio) in texture, che viene salvato in un file di un formato "font" interno (ho sviluppato il formato e il programma basato su http://content.gpwiki.org/index.php/OpenGL:Tutorials:Font_System sebbene la mia versione sia andata piuttosto lontano dal supporto originale Unicode e così via). Quando si avvia l'app principale, i font vengono caricati da questo formato "interno". Guarda il link sopra per maggiori informazioni.

Con tale approccio l'app principale non utilizza alcuna libreria speciale come FreeType, il che è indesiderabile anche per me. Il testo viene disegnato utilizzando le funzioni OpenGL standard.

+0

Se posso aggiungere qualcosa a questa alrea dy good answer, presta attenzione all'ottimizzazione di qualsiasi sistema di rendering di font in quanto potrebbe influire sulle prestazioni del tuo motore su risorse HW molto limitate come i dispositivi mobili. –

8

enter image description here

Usa glutStrokeCharacter(GLUT_STROKE_ROMAN, myCharString).

Un esempio: uno SCROLLER STAR WARS.

#include <windows.h> 
#include <string.h> 
#include <GL\glut.h> 
#include <iostream.h> 
#include <fstream.h> 

GLfloat UpwardsScrollVelocity = -10.0; 
float view=20.0; 

char quote[6][80]; 
int numberOfQuotes=0,i; 

//********************************************* 
//* glutIdleFunc(timeTick);     * 
//********************************************* 

void timeTick(void) 
{ 
    if (UpwardsScrollVelocity< -600) 
     view-=0.000011; 
    if(view < 0) {view=20; UpwardsScrollVelocity = -10.0;} 
    // exit(0); 
    UpwardsScrollVelocity -= 0.015; 
    glutPostRedisplay(); 

} 


//********************************************* 
//* printToConsoleWindow()    * 
//********************************************* 

void printToConsoleWindow() 
{ 
    int l,lenghOfQuote, i; 

    for( l=0;l<numberOfQuotes;l++) 
    { 
     lenghOfQuote = (int)strlen(quote[l]); 

     for (i = 0; i < lenghOfQuote; i++) 
     { 
      //cout<<quote[l][i]; 
     } 
      //out<<endl; 
    } 

} 

//********************************************* 
//* RenderToDisplay()      * 
//********************************************* 

void RenderToDisplay() 
{ 
    int l,lenghOfQuote, i; 

    glTranslatef(0.0, -100, UpwardsScrollVelocity); 
    glRotatef(-20, 1.0, 0.0, 0.0); 
    glScalef(0.1, 0.1, 0.1); 



    for( l=0;l<numberOfQuotes;l++) 
    { 
     lenghOfQuote = (int)strlen(quote[l]); 
     glPushMatrix(); 
     glTranslatef(-(lenghOfQuote*37), -(l*200), 0.0); 
     for (i = 0; i < lenghOfQuote; i++) 
     { 
      glColor3f((UpwardsScrollVelocity/10)+300+(l*10),(UpwardsScrollVelocity/10)+300+(l*10),0.0); 
      glutStrokeCharacter(GLUT_STROKE_ROMAN, quote[l][i]); 
     } 
     glPopMatrix(); 
    } 

} 
//********************************************* 
//* glutDisplayFunc(myDisplayFunction);  * 
//********************************************* 

void myDisplayFunction(void) 
{ 
    glClear(GL_COLOR_BUFFER_BIT); 
    glLoadIdentity(); 
    gluLookAt(0.0, 30.0, 100.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); 
    RenderToDisplay(); 
    glutSwapBuffers(); 
} 
//********************************************* 
//* glutReshapeFunc(reshape);    * 
//********************************************* 

void reshape(int w, int h) 
{ 
    glViewport(0, 0, w, h); 
    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    gluPerspective(60, 1.0, 1.0, 3200); 
    glMatrixMode(GL_MODELVIEW); 
} 

//********************************************* 
//* int main()        * 
//********************************************* 


int main() 
{ 
    strcpy(quote[0],"Luke, I am your father!."); 
    strcpy(quote[1],"Obi-Wan has taught you well. "); 
    strcpy(quote[2],"The force is strong with this one. "); 
    strcpy(quote[3],"Alert all commands. Calculate every possible destination along their last known trajectory. "); 
    strcpy(quote[4],"The force is with you, young Skywalker, but you are not a Jedi yet."); 
    numberOfQuotes=5; 

    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); 
    glutInitWindowSize(800, 400); 
    glutCreateWindow("StarWars scroller"); 
    glClearColor(0.0, 0.0, 0.0, 1.0); 
    glLineWidth(3); 

    glutDisplayFunc(myDisplayFunction); 
    glutReshapeFunc(reshape); 
    glutIdleFunc(timeTick); 
    glutMainLoop(); 

    return 0; 
} 
+46

glutStrokeCharacter non è una funzione opengl –

+15

si adatta a glxxx() requisito OP se :) :) – AndroidGecko

+1

Ecco il codice modificato per funzionare su Ubuntu (glutInit, include): https://gist.github.com/tgandor/3963f112324030a2c833 –

2

Caricare un'immagine con caratteri come trama e disegnare la parte di tale trama in base al carattere desiderato. È possibile creare tale texture utilizzando un programma di disegno, hardcode o utilizzare un componente di finestra per disegnare su un'immagine e recuperare quell'immagine per una copia esatta dei caratteri di sistema.

Non è necessario utilizzare Glut o qualsiasi altra estensione, solo l'operabilità OpenGL di base. Ottiene il lavoro fatto, senza contare che è stato fatto per decenni da programmatori professionisti in giochi di successo e altre applicazioni.

+1

Esistono persino programmi che è possibile utilizzare per generare la texture dell'immagine. – fintelia

36

Teoria

Perché è difficile

formati di font popolari come TrueType e OpenType sono formati contorno vettoriale: usano curve di Bezier per definire il contorno della lettera.

Image source.

Trasformare quei formati in array di pixel (rasterizzazione) è troppo specifica e fuori portata di OpenGL, specialmente perché OpenGL non ha primitive non rettilinee (es vedi Why is there no circle or ellipse primitive in OpenGL?)

L'approccio più semplice è quello di font primi raster noi stessi sulla CPU, e quindi dare l'array di pixel a OpenGL come una trama.

OpenGL quindi sa come gestire molto bene gli array di pixel attraverso le trame.

atlante Texture

Potremmo RASTER caratteri per ogni frame e ricreare le trame, ma che non è davvero efficace, specialmente se i caratteri hanno una dimensione fissa.

L'approccio più efficiente consiste nel rasterizzare tutti i caratteri che si prevede di utilizzare e racchiuderli su una singola trama.

E quindi trasferirlo alla GPU una volta e usarlo con le coordinate uv personalizzate per scegliere il carattere giusto.

Questo approccio è chiamato https://en.wikipedia.org/wiki/Texture_atlas e può essere utilizzato non solo per trame ma anche trame usate ripetutamente, come le tessere in un gioco 2D o le icone dell'interfaccia utente web.

L'immagine Wikipedia della struttura completa, che è a sua volta tratto da freetype-gl, illustra bene questo:

Ho il sospetto che l'ottimizzazione posizionamento carattere al più piccolo problema di struttura è un NP-hard problema, vedere: What algorithm can be used for packing rectangles of different sizes into the smallest rectangle possible in a fairly optimal way?

La stessa tecnica viene utilizzata nello sviluppo Web per trasmettere diverse piccole immagini (come icone) contemporaneamente, ma qui si chiama "CSS Sprites": https://css-tricks.com/css-sprites/ e vengono utilizzate per nascondere la latenza della rete invece di quello del Comunicazione CPU/GPU.

senza CPU metodi raster

Esistono anche metodi che non utilizzano il raster CPU alle texture.

Il rastering della CPU è semplice perché utilizza la GPU il meno possibile, ma iniziamo anche a pensare se sarebbe possibile utilizzare ulteriormente l'efficienza della GPU.

Questo FOSDEM 2014 il video https://youtu.be/LZis03DXWjE?t=886 spiega altre tecniche esistenti:

font all'interno della geometria 3D con la prospettiva

rendering dei font all'interno della geometria 3D con la prospettiva (a fronte di un HUD ortogonale) è molto più complicato, perché la prospettiva potrebbe rendere una parte del personaggio molto più vicina allo schermo e alla rger rispetto all'altra, effettuando una discretizzazione CPU uniforme (ad es. raster, tesselation) sembrano cattivi sulla parte vicina. Questo è in realtà un argomento di ricerca attiva:

enter image description here

campi Distanza sono una delle tecniche popolari ora.

Implementazioni

Gli esempi che seguono sono stati tutti testati su Ubuntu 15.10.

Poiché si tratta di un problema complesso come discusso in precedenza, la maggior parte degli esempi è di grandi dimensioni e potrebbe far esplodere il limite di 30k char di questa risposta, quindi è sufficiente clonare i rispettivi repository Git per compilare.

Sono tutti completamente open source, quindi è possibile solo RTFS.

soluzioni FreeType

FreeType appare come la libreria di rasterizzazione dei caratteri open source dominante, in modo che ci permetterebbe di utilizzare i font TrueType e OpenType, che lo rende la soluzione più elegante.

Esempi/tutorial:

Altri rasterizzatori carattere

Quelli sembrano meno buoni di FreeType, ma possono essere più leggero:

di Anton OpenGL 4 Tutorial esempio 26 "I caratteri bitmap"

Il font è stato creato dall'autore manualmente e memorizzato in un unico file .png. Le lettere sono memorizzate in forma di matrice all'interno dell'immagine.

Questo metodo non è ovviamente molto generale e avresti difficoltà con l'internazionalizzazione.

Build with:

make -f Makefile.linux64 

anteprima in uscita:

enter image description here

OpenGL dimostrativi capitolo 11 "font 2D"

texture sono generati da DDS files.

Il tutorial spiega come sono stati creati i file DDS, utilizzando CBFG e Paint.Net.

anteprima in uscita:

enter image description here

Per qualche ragione Suzanne manca per me, ma il contatore del tempo funziona bene: https://github.com/opengl-tutorials/ogl/issues/15

FreeGLUT

GLUT ha glutStrokeCharacter e FreeGLUT è open source ... https://github.com/dcnieho/FreeGLUT/blob/FG_3_0_0/src/fg_font.c#L255

OpenGLText

https://github.com/tlorach/OpenGLText

TrueType raster. Dal dipendente NVIDIA. Obiettivi per la riusabilità. Non l'ho ancora provato.

ARM Mali GLES SDK Esempio

http://malideveloper.arm.com/resources/sample-code/simple-text-rendering/ sembra di codificare tutti i caratteri su un PNG, e tagliarli da lì.

SDL_ttf

enter image description here

Fonte: https://github.com/cirosantilli/cpp-cheat/blob/d36527fe4977bb9ef4b885b1ec92bd0cd3444a98/sdl/ttf.c

vive in un albero separato per SDL, e si integra facilmente.

Non fornisce un'implementazione atlante trama però, quindi le prestazioni saranno limitati: Rendering fonts and text with SDL2 efficiently

discussioni Correlati