19. Texto con FTGL |
![]() |
![]() |
Videojuegos - Curso de Programación de juegos | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Escrito por Vicengetorix | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
![]() Ya vimos en su momento la forma de poner texto en pantalla pero el metodo que usamos entonces puede ralentizarnos el programa y es poco versatil, permite hacer pocas cosas con el texto. Si habeis navegado por internet buscando informacion sobre OpenGL, es probable que os hayais topado con el termino "textured fonts". Esto quiere decir escribir texto usando texturas (obvio), lo mismo que hacemos en los programas del curso con el cartel del logo de UnSitioWeb pero aplicado a letras. Este metodo es mas rapido que los "raster fonts", escribir los pixels de las letras a pantalla directamente, que es lo que haciamos con la forma antigua de escribir del curso, porque aprovecha la aceleracion grafica de la tarjeta. Para implementar texto con "textured fonts" habria que montarse un metodo para cargar la fuente del fichero en disco y luego los metodos necesarios para pintar texto usando la fuente cargada. Esto es un trabajo arduo que, por otro lado ya esta hecho de forma altruista. La libreria FreeType decodifica los ficheros de fuentes y es usada por FTGL para cargar fuentes para luego renderizarlas en OpenGL de varias posibles maneras. FTGL, pues, carga la fuente y renderiza texto a la manera "raster", a la manera "texture" o de forma poligonal y en 3D. Ademas le aplica suavizado (antialiasing) si es necesario para que se vea mejor. Todas estas razones me llevan a usar FTGL para el texto en nuestros programas. El uso de FTGL es muy facil y en la documentacion de la web queda muy claro; aun asi lo veremos y aclararemos aguna cosa. No explotaremos todo el potencial de FTGL, cada uno que llegue donde le interese. Partiremos del codigo del capitulo anterior, el 18. A medida que vayamos modificando el programa, no solo añadiremos cosas si no que tambien eliminaremos lo relativo a la forma antigua que teniamos de renderizar texto. Necesitaremos la libreria FTGL, claro, pero de su web se pueden solo bajar las fuentes. Para agilizar el tema he compilado yo la libreria FTGL para VC2005 y DEV-C (MinGW). Se puede bajar de la zona de descargas, de aqui, con sus cabeceras y con la libreria FreeType2 que es usada por FTGL. Con todo preparado comenzamos con las definiciones globales como de costumbre. Lo primero incluir las librerias.
Recordatorio: esta forma de incluir librerias a traves del codigo solo funciona con VC. Incluimos ahora el fichero de cabecera, no sin antes indicar con un define que vamos a usar una version de libreria estatica (no DLL).
Eliminamos codigo usado en nuestra forma anterior de renderizar texto.
Empezamos a usar FTGL creando los objetos de fuente necesarios. En el constructor indicamos el fichero de fuente a cargar ( .TTF por ejemplo). En el directorio "C:\WINDOWS\Fonts" encontraremos bastantes. Nosotros crearemos 3 objetos de fuente. Uno para la leyenda, otro para un texto grande que pondremos en pantalla y otro, de tipo "outline", para pintar un borde a las letras del segundo.
Dos puntualizaciones. Los ficheros de fuente pueden ser estos u otros: usad los que querais. Este codigo no comprueba que falle al cargar, eso alargaria el capitulo. Otra cosa. He puesto una linea comentada con la creacion de un objeto tipo "Pixmap" que es un tipo de fuente "raster", preparada para sustituir a la primera fuente. Esto es para poder comparar la velociadad del programa usando "raster fonts" y usando "texture fonts" y asi entender la importancia del tema. Hay otra linea comentada en la funcion Escribe(...) que se deberia descomentar para que funcionase con "Pixmap" la leyenda del programa. La funcion GeneraFuente() ya no es necesaria y la quitamos de nuestro codigo. En la funcion Escribe(...) hay cambios que hacer. No cambiamos nada hasta la funcion glOrtho que cambia. Al definir la proyeccion ortogonal debemos hacer un pequeño cambio para acomodarnos a como esta hecha FTGL, de forma que el origen de coordenadas pasara a estar abajo a la izquierda en vez de arriba a la izquierda. Esto nos obligara luego a hacer una resta cuando indiquemos la coordenada Y del texto a renderizar.
Al terminar de usar FTGL volveremos a usar nuestras proyecciones habituales. El siguiente bloque de codigo lo quitaremos al no ser ya util ...
... y lo sustituiremos por el siguiente codigo. Creamos un buffer para una cadena tipo UNICODE. Usaremos caracteres unicode para no tener problemas al usar tildes, la Ñ, apertura de exclamacion, apertura de interrogacion, dieresis, ... o cualquier caracter de cualquier idioma que no este entre los tipicos del ingles. Si usamos estos caracteres y los pasamos a FTGL como normales (ASCII), pueden pintarse cosas raras o peor, fallar el programa. De esta forma no hay problemas.
Despues convertimos el texto a imprimir en pantalla a UNICODE con una funcion que hace eso. De la funcion MultiByteToWideChar se puede consultar en la web sus parametros pero lo que hace es coger un buffer de tipo char, convertirlo a UNICODE y dejar el resultado en un buffer de tipo wchar_t (unicode).
256 es el tamaño del buffer unicode. Luego indicamos donde vamos a pintar de la pantalla. Recordad el tema del cambio de origen de coordenadas para FTGL. Tendremos que hacer una resta para la coordenada Y. La funcion Descender() del objeto de fuente retorna la distancia entre la linea base en que escribimos y la parte baja de la fuente (lo que baja la "j" del renglon, por ejemplo).
Esta seria la linea a descomentar si queremos probar los "PixmapFont":
Al final, con todo preparado, por fin pintamos el texto, el que esta en el buffer de texto unicode.
El resto de la funcion Escribe(...) no cambia. Su funcionamiento externo sera exactamente igual que antes pero con mejor resultado. Pasamos a la funcion Pinta() en la que renderizaremos un texto con borde. Tras pintar el cartel del logo de UnSitioWeb pinto el texto. Primero hago los preparativos habituales antes de pintar
Observad que nos hemos permitido, en la ultima funcion, rotar el texto un poco, eso se puede hacer ahora con los "Textured fonts". Ahora hay que renderizar el texto. Lo haremos con caracteres UNICODE para poder escribir con los caracteres propios de idiomas diferentes del ingles. Para ello pondremos una "L" antes de la cadena a renderizar. Si no lo hicieramos y usaramos, por ejemplo, una "ñ", o renderizaria mal el texto o podria fallar el programa. Cuidado con esto. Si estamos usando VC no hay problema poniendo una "L", pero si estuvieramos usando otro compilador, podria no entender la cadena con la "L" y dar un error de compilacion parecido a "illegal byte sequence" (MinGW). Deberiamos hacer la misma operacion que hemos hecho en la funcion Escribe(...).
Tras esto, vamos a poner un borde amarillo a las letras, escribiendo lo mismo en el mismo sitio pero con un tipo de fuente "OutlineFont".
No hemos indicado hasta ahora el tamaño de las letras. Lo haremos en la funcion IniciaGL(). Lo primero aqui sera eliminar lo que ya no hace falta.
La preparacion de las fuentes es minima. Le voy a indicar que no use display lists, que estan ya pasadas de moda y con los "OutlineFont" me han dado problemas (en algun PC me fallaba el programa). Le indico que use UNICODE, que ya lo selecciona por defecto pero por si acaso. Y le pongo el tamaño de la letra. Esta es una operacion pesada por lo que pongo el tamaño al inicializar y lo dejo fijo durante el programa. Si lo hiciera a cada frame, ralentizaria muchisimo. El tamaño que indicamos es en altura, desde la letra que mas baja a la letra mas alta de todo el conjunto de caracteres de la fuente. Luego, cuando indicamos donde se pinta la letra en el eje Y, estamos indicando la altura del renglon donde se escribe por lo que habra letras, como la "j" o la "g" que bajaran mas que la altura a la que le indicamos que escriba. Esta diferencia es la que nos retornaba la funcion Descender() que vimos en la funcion Escribe(...). La funcion Ascender() nos retornaria la distancia entre el renglon y la altura del caracter mas alto de la fuente.
Ya solo queda borrar una cosa antigua de la funcion ProcesaMensajes(...).
Al terminar la escena se veria asi. ![]() El codigo completo seria este: usw19.cpp . Recuerdo de nuevo que FTGL, ya compilada, se puede bajar de la zona de descargas, de aqui. ¡Sólo los usuarios registrados pueden escribir comentarios!
3.26 Copyright (C) 2008 Compojoom.com / Copyright (C) 2007 Alain Georgette / Copyright (C) 2006 Frantisek Hliva. All rights reserved." |