¿Cómo dibujar texto usando solo métodos OpenGL?

No tengo la opción de usar, pero los métodos OpenGL (es glxxx() 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?

Teoría

Por qué es difícil

Los formatos de fonts populares como TrueType y OpenType son formatos de contorno vectorial: usan curvas de Bezier para definir el límite de la letra.

Fuente de la imagen

La transformación de esos formatos en matrices de píxeles (rasterización) es demasiado específica y está fuera del scope de OpenGL, especialmente porque OpenGl no tiene primitivas no rectas (por ejemplo, vea ¿Por qué no hay círculo o primitiva de elipse en OpenGL? )

El enfoque más sencillo es utilizar las primeras fonts de ráster en la CPU y luego asignar la matriz de píxeles a OpenGL como textura.

OpenGL entonces sabe cómo manejar arreglos de píxeles a través de texturas muy bien.

Atlas de textura

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

El enfoque más eficiente es rastrear todos los caracteres que planea usar y meterlos en una sola textura.

Y luego transfiéralo a la GPU una vez, y utilícelo texturas con coordenadas uv personalizadas para elegir el personaje correcto.

Este enfoque se llama https://en.wikipedia.org/wiki/Texture_atlas y se puede utilizar no solo para texturas sino también para otras texturas usadas repetidamente, como mosaicos en un juego 2D o íconos de interfaz de usuario web.

La imagen de Wikipedia de la textura completa, que en sí misma está tomada de freetype-gl, ilustra esto bien:

Sospecho que la optimización de la colocación de caracteres para el problema de textura más pequeño es un problema NP-hard, consulte: ¿Qué algoritmo se puede utilizar para empaquetar rectangularjs de diferentes tamaños en el rectángulo más pequeño posible de una manera bastante óptima?

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

Métodos ráster sin CPU

También existen métodos que no usan el ráster de la CPU para texturas.

El raspado de la CPU es simple porque usa la GPU lo menos posible, pero también comenzamos a pensar si sería posible usar aún más la eficiencia de la GPU.

Este video de FOSDEM 2014 https://youtu.be/LZis03DXWjE?t=886 explica otras técnicas existentes:

  • tesselación: convierta la fuente a triangularjs diminutos. La GPU es realmente buena para dibujar triangularjs. Desventajas:
    • genera un grupo de triangularjs
    • Cálculo de CPU O (n log n) de los triangularjs
  • calcular curvas en sombreadores. Un documento de 2005 de Blinn-Loop puso este método en el mapa. Desventaja: complejo. Ver: Dibujo de bezier cúbico independiente de resolución en GPU (Blinn / Loop)
  • implementaciones directas de hardware como OpenVG https://en.wikipedia.org/wiki/OpenVG . Desventaja: no muy implementada por alguna razón. Ver:
    • OpenGL, OpenVG. Dibujar texto?
    • Implementación de OpenVG?

Fuentes dentro de la geometría 3D con perspectiva

Renderizar fonts dentro de la geometría 3D con perspectiva (en comparación con un 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 más grande que la otra, haciendo una discretización uniforme de la CPU (por ejemplo, raster tesselación) se ven mal en la parte más cercana. Este es en realidad un tema de investigación activo:

enter image description here

Los 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 solo clone los repositorys Git respectivos para comstackr.

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 fonts de código abierto dominante, por lo que nos permitiría usar fonts TrueType y OpenType, por lo que es la solución más elegante.

Ejemplos / tutoriales:

Otros rasterizadores de fonts

Esos parecen menos buenos que FreeType, pero pueden ser más livianos:

Ejemplos de tutoriales de OpenGL 4 de Anton 26 “Fuentes de bitmap”

La fuente fue creada por el autor de forma manual y almacenada 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 “Fuentes 2D”

Las texturas se generan a partir de archivos DDS .

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 me falta, pero el contador de tiempo funciona bien: https://github.com/opengl-tutorials/ogl/issues/15

FreeGLUT

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

OpenGLText

https://github.com/tlorach/OpenGLText

Ráster TrueType. Por empleado de NVIDIA. Tiene como objective la reutilización. No lo he intentado todavía

Muestra de ARM Mali GLES SDK

http://malideveloper.arm.com/resources/sample-code/simple-text-rendering/ parece codificar todos los caracteres en un PNG, y cortarlos desde allí.

SDL_ttf

enter image description here

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

Vive en un árbol separado para SDL, y se integra fácilmente.

Sin embargo, no proporciona una implementación de atlas de texturas, por lo que el rendimiento será limitado: ¿cómo renderizar fonts y texto con SDL2 de manera eficiente?

Temas relacionados

  • ¿Cómo hacer OpenGL live text-rendering para una GUI?
  • Representación de texto / fuente en OpenGLES 2 (iOS – CoreText?) – ¿opciones y mejores prácticas?

enter image description here

Usa glutStrokeCharacter(GLUT_STROKE_ROMAN, myCharString) .

Un ejemplo: un STAR WARS SCROLLER.

 #include  #include  #include  #include  #include  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 

Dibujar texto en OpenGL no es una tarea directa. 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 para 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 fuente.

Este artículo describe cómo renderizar texto en OpenGL usando varias técnicas.

Con solo usar OpenGL, hay varias formas:

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

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 progtwig de pintura, codificarlo o usar un componente de ventana para dibujar una imagen y recuperar esa imagen para obtener una copia exacta de las fonts del sistema.

No es necesario 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 progtwigdores profesionales en juegos exitosos y otras aplicaciones.

Creo que la mejor solución para dibujar texto en OpenGL son las fonts de textura. Trabajo con ellas durante mucho tiempo. Son flexibles, rápidos y bonitos (con algunas excepciones posteriores). Utilizo un progtwig especial para convertir archivos de fonts (.ttf, por ejemplo) en texturas, que se guardan en archivos de algún formato interno de “fuente” (he desarrollado formatos y progtwigs basados ​​en http://content.gpwiki.org/index). .php / OpenGL: Tutorials: Font_System, aunque mi versión fue bastante lejos de la original de Unicode, y así sucesivamente). Al iniciar la aplicación principal, las fonts se cargan desde este formato “interno”. Mire el enlace de arriba para más información.

Con ese enfoque, la aplicación principal no usa ninguna biblioteca especial como FreeType, lo que tampoco me conviene. El texto se dibuja utilizando las funciones estándar de OpenGL.