2012-01-13 23 views
27

No tengo opciones para usar que no sean métodos opengl (es decir, métodos glxxx()()). Necesito dibujar texto usando solo métodos gl. Después de leer el libro rojo entiendo que solo es posible a través del método glBitmap(). Si esta es la única forma posible, entonces ¿alguien me puede ayudar con la información de la matriz de píxeles para todos los personajes? ¿Hay alguna otra forma de dibujar texto?¿Cómo dibujar texto usando solo métodos OpenGL?

Respuesta

5

This article describe cómo representar texto en OpenGL utilizando diversas técnicas.

Con solamente usando OpenGL, hay varias maneras:

  • utilizando glBitmap
  • utilizando texturas
  • usando listas de visualización
7

Dibujo texto en OpenGL llano no es un straigth- tarea de reenvío Probablemente debería echar un vistazo a las bibliotecas para hacer esto (ya sea mediante el uso de una biblioteca o como una implementación de ejemplo).

Algunos buenos puntos de partida podrían ser GLFont, OpenGL Font Survey y NeHe Tutorial for Bitmap Fonts (Windows).

Tenga en cuenta que los mapas de bits no son la única forma de lograr texto en OpenGL como se menciona en la encuesta de la fuente.

+0

gracias por Nehe enlace tutorial – befzz

1

creo que la mejor solución para dibujar texto en OpenGL es fuentes textura, trabajo con ellos durante mucho tiempo. Son flexibles, rápidos y bonitos (con algunas excepciones posteriores). Utilizo un programa especial para convertir archivos de fuentes (.ttf por ejemplo) en texturas, que se guardan en archivos de algún formato interno de "fuente" (he desarrollado formatos y programas basados ​​en http://content.gpwiki.org/index.php/OpenGL:Tutorials:Font_System aunque mi versión fue bastante lejos del soporte original Unicode, etc.). Al iniciar la aplicación principal, las fuentes se cargan desde este formato "interno". Mire el enlace de arriba para más información.

Con tal enfoque principal de la aplicación no utiliza ninguna bibliotecas especiales como FreeType, que no es deseable para mí también. El texto se dibuja utilizando las funciones estándar de OpenGL.

+0

Si puedo agregar algo a esto alrea De buena respuesta, preste atención a la optmización de cualquier sistema de representación de fuentes, ya que puede afectar el rendimiento de su motor en recursos HW muy limitados, como los dispositivos móviles. –

8

enter image description here

Uso glutStrokeCharacter(GLUT_STROKE_ROMAN, myCharString).

Un ejemplo: A STAR WARS SCROLLER.

#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 no es una función opengl –

+15

cabe en glxxx() Requisito OP aunque :) – AndroidGecko

+1

Aquí está el código modificado para trabajar en Ubuntu (glutInit, incluye): https://gist.github.com/tgandor/3963f112324030a2c833 –

2

Cargue una imagen con caracteres como textura y dibuje la parte de esa textura según el carácter que desee. Puede crear esa textura usando un programa de pintura, codificarlo o usar un componente de ventana para dibujar una imagen y recuperar esa imagen para obtener una copia exacta de las fuentes del sistema.

No necesita utilizar Glut o cualquier otra extensión, solo la operatividad básica de OpenGL. Hace el trabajo, sin mencionar que ha sido hecho así durante décadas por programadores profesionales en juegos exitosos y otras aplicaciones.

+1

Incluso hay programas que puede usar para generar la textura de la imagen para usted. – fintelia

36

Teoría

por qué es difícil

formatos de fuentes populares como TrueType y OpenType son formatos del vector esquema: utilizan las curvas de Bézier para definir el límite de la carta.

Image source.

La transformación de esos formatos en matrices de píxeles (rasterización) es demasiado específica y fuera del alcance de OpenGL, especialmente porque OpenGL no tiene primitivas no rectas (por ejemplo, ver Why is there no circle or ellipse primitive in OpenGL?)

El método más sencillo consiste en fuentes primeras de trama nosotros mismos en la CPU, y luego dar la matriz de píxeles a OpenGL como una textura.

OpenGL entonces sabe cómo hacer frente a las matrices de píxeles a través de texturas muy bien.

atlas textura

Podríamos Raster caracteres para cada cuadro y volver a crear las texturas, pero eso no es muy eficiente, especialmente si los personajes tienen un tamaño fijo.

El enfoque más eficiente es a raster todos los caracteres que desee usar y meter ellos en una sola textura.

y luego transferir a la GPU que una vez, y lo utilizan con textura UV encargo coordina para elegir el carácter correcto.

Este enfoque se denomina https://en.wikipedia.org/wiki/Texture_atlas y puede ser utilizado no sólo para las texturas, sino también otras texturas utilizadas en varias ocasiones, como las tejas en un juego o la interfaz de usuario web de iconos 2D.

La imagen de Wikipedia de la textura completa, que a su vez se ha tomado de freetype-gl, ilustra esto muy bien:

sospecho que la optimización de la colocación de caracteres al problema de textura más pequeño es un NP-duro problema, consulte: What algorithm can be used for packing rectangles of different sizes into the smallest rectangle possible in a fairly optimal way?

La misma técnica se utiliza en el desarrollo web para transmitir varias imágenes pequeñas (como iconos) a la vez, pero allí se llama "CSS Sprites": https://css-tricks.com/css-sprites/ y se utilizan para ocultar la latencia de la red en lugar de la de la Comunicación CPU/GPU.

métodos de mapa de bits sin CPU

También existen métodos que no utilizan la trama de la CPU a las texturas.

CPU Barrido de es simple, ya que utiliza la GPU lo menos posible, pero también empezar a pensar si sería posible utilizar la eficiencia de GPU más.

Este vídeo FOSDEM 2014 https://youtu.be/LZis03DXWjE?t=886 explica otras técnicas existentes:

Fuentes dentro de la geometría 3D con perspectiva

Rendering fuentes dentro de la geometría 3D con perspectiva (en comparación con un sistema HUD ortogonal) es mucho más complicado, porque la perspectiva podría hacer que una parte del personaje esté mucho más cerca de la pantalla y la más rápido que el otro, haciendo una discretización uniforme de CPU (p. raster, tesselación) se ven mal en la parte más cercana. Esto es en realidad un tema de investigación activa:

enter image description here

campos de distancia son una de las técnicas populares ahora.

Implementaciones

Los ejemplos que siguen fueron todos probados en Ubuntu 15.10.

Debido a que este es un problema complejo como se discutió anteriormente, la mayoría de los ejemplos son grandes y explotarían el límite de 30k de esta respuesta, así que simplemente clone los repositorios Git respectivos para compilar.

Sin embargo, todos son de código abierto, por lo que solo puede RTFS.

soluciones FreeType

FreeType se parece a la biblioteca de rasterización de fuente de código abierto dominante, por lo que nos permitirá utilizar las fuentes TrueType y OpenType, por lo que es la solución más elegante.

Ejemplos/tutoriales:

Otros rasterizadores fuente

Aquellos parecen menos buena que FreeType, pero pueden ser más liviano:

OpenGL 4 Tutoriales ejemplo 26 "fuentes de mapa de bits" de Anton

La fuente fue creado por el autor de forma manual y se almacena en un solo archivo .png. Las letras se almacenan en forma de matriz dentro de la imagen.

Este método, por supuesto, no es muy general, y tendría dificultades con la internacionalización.

Construir con:

make -f Makefile.linux64 

vista previa de salida:

enter image description here

OpenGL-tutorial Capítulo 11 "2D" fuentes

texturas se genera a partir de DDS files.

El tutorial explica cómo se crearon los archivos DDS, utilizando CBFG y Paint.Net.

vista previa de salida:

enter image description here

Por alguna razón Suzanne falta para mí, pero el contador de tiempo funciona bien: https://github.com/opengl-tutorials/ogl/issues/15

freeglut

GLUT tiene glutStrokeCharacter y freeglut es código abierto ... https://github.com/dcnieho/FreeGLUT/blob/FG_3_0_0/src/fg_font.c#L255

OpenGLText

https://github.com/tlorach/OpenGLText

trama TrueType. Por empleado de NVIDIA. Tiene como objetivo la reutilización. No lo he intentado todavía

ARM Mali GLES SDK Muestra

http://malideveloper.arm.com/resources/sample-code/simple-text-rendering/ parece codificar todos los caracteres en un PNG, y se cortan a partir de ahí.

SDL_ttf

enter image description here

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

vive en un árbol separado a SDL, y se integra fácilmente.

no proporciona una aplicación atlas textura sin embargo, lo que el rendimiento se limitará: Rendering fonts and text with SDL2 efficiently

las discusiones relacionadas

Cuestiones relacionadas