2009-02-04 9 views
24

Estoy tratando de encontrar un simple para dibujar texto en OpenGL. Mi investigación ha demostrado que es una tarea bastante compleja. Implica crear (o generar en tiempo de ejecución) una textura de atlas de fuente y luego crear un cuadrángulo para cada letra con las coordenadas de colocación y textura correctas.¿Existe una biblioteca decente de dibujo de texto OpenGL para el SDK de iPhone?

He oído algunas cosas buenas sobre freetype, pero he encontrado muy poco sobre cómo ejecutarlo en el iPhone, y parece ser bastante complejo.

¿Hay alguna biblioteca de texto OpenGL envuelta en Objective-C que funcione con el SDK de iPhone que las personas han estado usando? ¿O estoy por encima de pensar esto y hay un enfoque más fácil que me estoy perdiendo?

+0

[Esto se ve muy bien] (http: // código .google.com/p/freetype-gl /) – bobobobo

Respuesta

8

Su descripción de usar freetype para crear un atlas de textura junto con toda la información de glifos es exactamente lo que estoy haciendo en mi proyecto actual de iPhone.

Realizo todo el análisis sintáctico de la fuente en un paso previo al proceso (Todo en C# en Windows como ocurre). El atlas en sí mismo se genera y contiene solo los caracteres necesarios: para reducir el espacio, también a veces termino generando más de un atlas para mantener las texturas en tamaños pow2 y de una resolución sensata.

Puede extraer fácilmente la información de glifos del tipo de freetype. Transfiere eso a tu aplicación junto con las texturas en tiempo de ejecución y luego es bastante trivial simplemente alterar los coords UV de la textura según sea necesario.

Por lo que vale la pena, esto es cómo definir un carácter glifo dentro de mi pequeño motor:

struct FontGlyph 
{ 

u32 char_code; 

u32 m_x;    // base x position on tpage 

u32 m_y;   // base y position on tpage 

u32 m_width;   // glyph width 

u32 m_height;   // glyph height 

i32 m_horiBearingX;  // Distance to X shift 

i32 m_horiBearingY;  // Distance to Y shift 

u32 m_horiAdvance;  // Total Horizontal advance this character requires 

u32 m__tpage_index;  // Which tpage does this glyph use? 

}; 

entonces tengo un objeto 'SpriteString', que se comporta más o menos como cualquier otra cadena, además de lo puede dibujarlo usando sprites ....

Estoy de acuerdo en que todo esto puede parecer un gran trabajo para un problema bastante trivial, pero he descubierto que me ha dado mucha flexibilidad y realmente no tardé mucho en implementar cuando llegué a eso.

No dude en responder o comentar si necesita más información. (Y buena suerte :)


respuesta a su comentario como me quedé sin espacio en la sección de comentarios ...

Mira la documentación freetype, que básicamente le da los datos de glifo y sin perder el tiempo , simplemente lo saca de la fuente. En cuanto a las texturas en sí, obtienes el tipo de freet para representar cada glifo, y luego lo administras para construir la textura. Esto lo hago como un proceso previo completamente separado de mi aplicación principal.

He aquí un extracto de mi código de la herramienta que hace esto: http://pastebin.com/md1c6354

Tenga en cuenta, sin embargo, esto fue sólo ha dirigido a los ojos y no para el consumo público, por lo que excusa el hecho de que es desordenado como el infierno :)

+0

Esta estructura definitivamente me ayuda a entender todos los pasos involucrados. Gracias. Sin embargo, ¿cómo podría generar las texturas y los datos de glifos? –

+0

Gracias, Esta puede terminar siendo la mejor ruta. Si se me ocurre una solución decente, intentaré terminar bien y lanzarla a Github para que todos la compartan. –

+0

Magnífico: manténganme informado :) –

1

Compruebe la demo de aterrizaje forzoso. La clase Texture2D que se proporciona permite la creación de texturas con texto y una fuente. (Esperemos que haya una mejor respuesta Me encantaría una forma más simple de dibujar en una vista de apertura)

+0

Creo que no es exactamente lo que estoy buscando. Creo que eso crea textura para toda una cadena sobre la marcha, que es una operación intensiva de la CPU. Estoy buscando más de una forma de construir palabras a partir de cuadrantes individuales para que pueda representar texto arbitrario en tiempo de ejecución. Esto debería ser mucho más rápido. –

+0

¿Por qué crees que tu propuesta sería más rápida? – Jacob

+0

No se puede dibujar a una vista sin una textura, simplemente no se ejecutaría lo suficientemente rápido – bobobobo

22

Una forma de hacerlo es configurando un UILabel y luego renderizando su capa en una textura. Una ruta indirecta a esto sería configurar primero el UILabel con texto, fuente, etc.y luego use el siguiente código

UIGraphicsBeginImageContext(yourLabel.frame.size); 
[yourLabel.layer renderInContext:UIGraphicsGetCurrentContext()]; 
UIImage *layerImage = UIGraphicsGetImageFromCurrentImageContext(); 
UIGraphicsEndImageContext(); 

para capturar el UILabel en un UIImage. Luego puede usar el constructor initWithImage: de la clase Texture2D en el proyecto CrashLanding para transformarlo en una textura.

Parece initWithImage: en ese ejemplo vuelve a presentar el UIImage en un contexto de mapa de bits y lo usa para crear la textura. Con un poco de trabajo, puede extraer el código relevante de ese método y modificar el código anterior para convertir su capa directamente en la textura.

De esta manera, obtiene el agradable soporte Unicode y fuente de UILabel al crear el texto para su textura.

+0

Estoy tratando de evitar generar una textura diferente sobre la marcha para cada cadena procesada Mi aplicación tendría muchas cadenas diferentes que se muestran y parece que esto supondría una gran carga para la CPU y la memoria. –

+2

Esto es efectivamente lo que hace el iPhone por cada texto que ve. Todos los UILabels están respaldados por CALayer, y CALayers son texturas de OpenGL simplemente envueltas. No creo que esto sea una fuente de recursos tan completa como cree. –

+0

La aplicación demo de aterrizaje forzoso ya no parece estar disponible para descargar desde el sitio del desarrollador de iphone, ¿hay alguna alternativa adecuada? ? – rck

6

Encontré una solución simple para esto. Aquí hay una función rápida que escribí para ella. (Tendrá la clase Texture2D.)

- (void) drawText:(NSString*)theString AtX:(float)X Y:(float)Y { 
// Use black 
glColor4f(0, 0, 0, 1.0); 

// Set up texture 
Texture2D* statusTexture = [[Texture2D alloc] initWithString:theString dimensions:CGSizeMake(150, 150) alignment:UITextAlignmentLeft fontName:@"Helvetica" fontSize:11]; 

// Bind texture 
glBindTexture(GL_TEXTURE_2D, [statusTexture name]); 

// Enable modes needed for drawing 
glEnableClientState(GL_TEXTURE_COORD_ARRAY); 
glEnableClientState(GL_VERTEX_ARRAY); 
glEnable(GL_TEXTURE_2D); 
glEnable(GL_BLEND); 

glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); 

// Draw 
[statusTexture drawInRect:CGRectMake(X,Y-1,1,1)]; 

// Disable modes so they don't interfere with other parts of the program 
glDisableClientState(GL_TEXTURE_COORD_ARRAY); 
glDisableClientState(GL_VERTEX_ARRAY); 
glDisable(GL_TEXTURE_2D); 
glDisable(GL_BLEND);  
} 

Creo que la entrada de coordenadas deben estar en su mundo coordina, pero no estoy seguro si eso es cierto en general o si simplemente funciona de esa manera para mí. Es posible que necesite jugar con las compensaciones para hacerlo bien.

+5

una pérdida de memoria con statusTexture? –

+0

La solución de Tony Tonev funcionó para mí. Recibí texture2D del enlace de Dustin. Solución muy limpia. Fácil de agregar el almacenamiento en caché más tarde si es necesario. – Voltron

3

Gracias por ese método. Me salvó un tiempo.

Hubo un par de cosas que tuve que cambiar. La llamada glBlendFunc tenía que ser:

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_ALPHA) 

Y en segundo lugar, el texto parece estar llegando en un solo punto. La llamada CGRectMake crea un rectángulo de 1x1, a menos que lo lea incorrectamente.

3

utilizar la biblioteca "reflexiones" font:

http://www.themusingsofalostprogrammer.com/2010/01/how-to-do-font-rendering-in-opengl-on.html

Font font("Verdena"); 
font.print("Hello World!", x, y, z); 

fácil :)

Viene con soporte Unicode, cargas glifos "a la carta", e incluso tiene una forma a las variables de salida

font.print(x, y, z) << "fps: " << fps; 
+1

Eso se ve muy malditamente sexy. –

+2

Esta biblioteca carga cada carácter como una textura separada, que será muy lenta si está haciendo una cantidad de dibujo del tamaño decente. Es * mucho * mejor utilizar un atlas de textura, como lo sugieren algunas de las otras respuestas. –

+0

Es triste que esto esté en OpenGL ES 1 (no 2), y el enlace de descarga ya no funciona ... – Xys

1

Sí, th Hay 2 que conozco de. El truco es que debes renderizar la textura usando Quartz (funciones CGContext *) y luego renderizar esa textura para que el usuario la vea.

Si le preocupa el rendimiento, también puede usar Quartz para generar su atlas de textura.

Es bastante fácil de impulsar una herramienta de generación de texturas (en xCode) once you know the basics of rendering a font.

Todo lo que tienes que hacer es tener un CGContext válido. Puede encontrar un código de muestra muy bueno en este texture loader.

Básicamente el código va:

// Create the cgcontext as shown by links above 

// Now to render text into the cg context, 
// the drop the raw data behind the cgcontext 
// to opengl. 2 ways to do this: 
// 1) CG* way: (advantage: easy to use color) 
CGContextSelectFont(cgContext, "Arial", 24, kCGEncodingMacRoman); 

// set color to yellow text 
CGContextSetRGBFillColor(cgContext, 1, 1, 0, 1) ; // Be sure to use FILL not stroke! 

// draw it in there 
CGContextShowTextAtPoint(cgContext, 20, 20, "HI THERE", strlen("HI THERE")) ; 

/* 
// WAY #2: this way it's always black and white 
// DRAW SOME TEXT IN IT 
// that works ok but let's try cg to control color 
UIGraphicsPushContext(cgContext); 
UIFont *helv = [UIFont fontWithName:@"Helvetica" size:[UIFont systemFontSize]]; 
NSString* msg = @"Hi hello" ; 
[msg drawInRect:CGRectMake(0,0,pow2Width,pow2Height) withFont:helv] ; 
    UIGraphicsPopContext(); 
*/ 

// put imData into OpenGL's memory 
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, pow2Width, pow2Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imData); 
CHECK_GL ; 

sale bastante bien y antialiased,

tex atlas

Una lista de fuentes IOS es available here, y con prerenders here

2

I He creado una clase de fuente similar a la biblioteca de fuentes "meditaciones", menos las pérdidas de memoria y menos el te creación de la textura para cada personaje, cada cuadro. Todavía usa una glTexture diferente para cada personaje. Nota: Texture2D se ha cambiado para comentar su eliminación de textura.

init en el constructor: _font = new Font("Helvetica", 40);

uso en volver a dibujar() Método: _font->draw("Hello, World!", 50, 100, ALIGN_LEFT);

GitHub enlace:

https://github.com/chandl34/public/tree/master/personal/c%2B%2B/Font

+0

¿Sabes si hay un equivalente para OpenGLES 2.0? Gracias por adelantado – Xys

Cuestiones relacionadas