"Ningún juego dura tanto hasta que te lo terminas como el que te programas tú mismo,
ninguno te absorbe tanto y ninguno te produce tanta satisfacción cuando lo has acabado"
Programacion de videojuegos
Inicio Curso de programación de juegos 9. Listas, Texto y FPS
Domingo 22 de Octubre del 2017

Menu principal
Colaborar (con PayPal)

Para continuar con el trabajo de esta Web y poder pagar el hosting, viene bien la ayuda que sea. Gracias a todos.

Importe: 

Ultimas descargas
19.Jan

Clase que permite dibujar texto en OpenGL con mucha facilidad.Usa FreeType2.Para ver que hace y c...


9. Listas, Texto y FPS Imprimir Correo electrónico
Videojuegos - Curso de Programación de juegos
Escrito por Vicengetorix   
Índice de Artículos
9. Listas, Texto y FPS
Texto
Velocidad y FPS
Todas las páginas
En este capitulo veremos una serie de cosas tan necesarias como cualquier otra cosa pero menos vistosas, aunque el texto en pantalla nos hace falta ya como el comer. Cuando seamos capaces de hacer una especie de "printf" en OpenGL, lo usaremos para saber los Frames Por Segundo (FPS), la velocidad a la que nuestro programa se mueve y controlarla.





Lo primero para cumplir los objetivos de este capitulo es aprender lo que son las "listas de pintado" en OpenGL (Display List).

El concepto es facil. Tengo un numero de vertices (por ejemplo los de nuestro cubo) que voy a pintar varias veces porque quiero poner varios cubos iguales en mi escena. En vez de pintar varias veces el cubo en cada frame (un frame es como un fotograma, cada vez que pinto la escena), le mando a OpenGL los datos de mi cubo con un identificativo y cada vez que lo quiero pintar le digo a OpenGL que pinte el cubo (con los datos que le pase antes), mediante este identificativo.
Resumiendo. Primero le paso a OpenGL los datos del cubo, fuera de la funcion Pinta(), y cuando quiero pintar el cubo solo tengo que decirle que lo pinte, 1, 2, 3,.. o 300 veces.

Ahora veremos como hacemos esto de forma practica. Empezaremos con el codigo del capitulo anterior, en la version de luz puntual.

Definimos una variable de tipo GLuint global para almacenar el identificativo de la lista que vamos a crear.

1
2
3
4
// Variable de tipo unsigned int para guardar 
// el identificativo de la "display list"
GLuint Cubo;
 

Lo primero, por ordenar un poco el programa vamos a sacar de la funcion Pinta() el codigo con el que pintabamos el cubo y lo pasaremos a otra funcion en la que generaremos la lista. Esta funcion la llamaremos GeneraLista().

Lo primero sera generar el identificativo para la lista con la funcion glGenLists. Esta funcion tiene como parametro en numero de listas a generar (en nuestro caso 1) y retorna el identificativo.

Luego con la funcion glNewList indicamos a OpenGL que empezamos a indicarle las instrucciones que debe guardar en la lista.
Los parametros son el identificativo de la lista y GL_COMPILE.

1
2
3
4
5
6
7
8
// Genero una (1) lista y guardo el 
// identificativo en "Cubo"
Cubo = glGenLists(1);
// Esta funcion es la que marca el inicio
// de la definicion de la lista.
// Todas las funciones OpenGL entre esta
// funcion y glEndList() se guardaran en la lista.
glNewList(Cubo, GL_COMPILE);

Tras este codigo van todas las funciones con las que pintabamos el cubo, desde glBegin a glEnd, y que hemos borrado de la funcion Pinta() y pasado aqui.
Al final terminamos con la creacion de la lista poniendo la funcion glEndList().

1
2
// Fin de la creacion de la lista.
glEndList();

Con esto terminamos la funcion GeneraLista().

Conviene aclarar que entre las funciones de inicio y fin de la generacion de la lista se puede incluir, por ejemplo, las funciones glVertex dentro de un bucle for o while y pasar las coordenadas en variables. En la lista se almacenara solo los datos que finalmente, como resultado del algoritmo que hagas, se envian a la tajeta de video (glVertex, glNormal, glTexCoord, ..., solo almacena lo relativo a OpenGL y con datos concretos), asi que no se puede guardar en una lista  un algoritmo que genere diferentes formas en base a variables. Solo guarda datos de vertices concretos y exclusivamente datos OpenGL.

Luego nos queda usar la lista generada en la funcion Pinta().

Aqui ya no estaba el codigo para pintar nuestro cubo, lo habiamos pasado a la funcion GeneraLista(), y ahora para pintar nuestro cubo deberemos invocar esta lista que hemos crado con la funcion glCallList(...) pasandole como parametro la variable que contiene el identificativo de la lista que contiene nuestro cubo: glCallList(Cubo).

Asi pues, incluiremos nuevo codigo donde estaba antes el codigo delimitado por glBegin(...) y glEnd(), estas dos funciones incluidas (quiero decir que ya no hacen falta, que las hemos puesto al crear la lista):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// En vez de pintar el cubo con todas las funciones 
// glVertex, glNormal y glTexCoord, solo tengo
// que ejecutar la lista "Cubo".
glCallList(Cubo);
 
// Pinto otro cubo un poco mas lejos
glTranslatef(0,0,-2.0f);
glCallList(Cubo);
 
// Desabilito pintar con texturas para pintar
// otros dos cubos blancos
glDisable(GL_TEXTURE_2D);
 
// Pinto otro cubo, ya sin textura a un lado.
glTranslatef(2,0,2.0f);
glCallList(Cubo);
 
// Pinto otro cubo mas lejano.
glTranslatef(2,0,-4.0f);
glCallList(Cubo);
 

En este codigo hemos pintado 4 cubos, en vez de el unico cubo que pintabamos antes.
Cada funcion glCallList(cubo) del codigo pinta un cubo. El primero se pintara donde se pintaba el cubo original, y los otros los hemos puesto en otros lugares de nuestra escena, moviendolos con glTranslate (observa que no hemos cargado la matriz identidad entre una funcion glTranslate y otra, por lo que las traslaciones se sumaran, si antes he movido un cubo 2 y ahora muevo otro cubo otros 2, el segundo cubo se habra movido 4 en total, 2+2).

Aqui aprovecho para hacer una apreciacion sobre las transformaciones y rotaciones que puede que os ahorre bastante tiempo, que de otro modo tendriais que perder hasta dar con el motivo por el que los objetos no se ponen donde quereis.
En OpenGL no es lo mismo mover y rotar que rotar y mover.
Para entenderlo mejor. Cuando movemos o rotamos no estamos haciendolo sobre el objeto si no sobre el eje de coordenadas.
Si giramos el eje de coordenadas 90 grados respecto al eje Y, si luego movemos hacia el eje Z, no mandaremos al objeto hacia el fondo de la pantalla si no hacia un lado. No veremos el objeto que pretendemos colocar el pantalla, porque habremos puesto el eje Z donde antes estaba el eje X.
En cambio si movemos hacia el eje Z primero veremos el objeto tan lejos como hayamos movido. Si luego giramos, estaremos girando el objeto sobre su propio eje pero todavia en el mismo lugar del espacio.
Graficamente:

Gira y mueve:


Mueve y gira:


Esta claro que aqui el orden si altera el producto (de matrices).

Continuamos.
Tambien he desabilitado las texturas - glDisable(GL_TEXTURE_2D) - tras el segundo cubo, para dibujar los 2 primeros con textura y los 2 ultimos solo con el material que habiamos definido para el cubo (mas o menos blanco).

Tras esto ya no tengo que desabilitarlas antes de pintar la esfera.

Solo nos queda un detalle para que el resultado de nuestro programa, modificado para usar "display list" sea el deseado. Incluimos una llamada a la funcion GeneraLista() dentro de la funcion IniciaGL(), al final. Si no lo hicieramos, el programa nunca pasaria por el codigo que genera la lista y no podria luego pintarla.

1
2
3
// LLamo a la funcion que creamos para generar la lista. 
GeneraLista();
 

Tambien tenemos la opcion de borrar las listas creadas si queremos reusar los indices con la funcion glDeleteLists(...), que permite borrar un indice o un rango de ellos.

El resultado en pantalla seria asi:


El codigo completo es este: usw9a.cpp




¡Sólo los usuarios registrados pueden escribir comentarios!
+/- Comentarios
Buscar
Mario  - Preguntilla   |186.104.20.xxx |11-07-2010 21:06:24
Hola. Me gustaría saber que habría que agregarle a la función Escribe() para
poder cambiar la fuente de esta cada vez que aparezca.

Gracias de antemano
Vicengetorix   |194.179.126.xxx |12-07-2010 11:55:23
Habría que generar los display list de la otra fuente, tal y como hemos hecho
con la primera, y a la hora de estribir, antes, habría que cambiar la base de
las listas (glListBase) para que apunte a la segunda fuente.
Para elegir entre
fuentes se podría hacer añadiendo un parámetro a la función.
jromerorasero  - Duda al inicializar la lista de fuentes   |87.220.201.xxx |05-03-2010 22:25:18
Buenas tardes.
Tengo una dudilla, y es que al llamar a GeneraFuente() desde
IniciaGL() yo la puse al final de la función, junto a GeneraLista(). Si hacía
esto no obtenía ningún resultado en la pantalla, ¿puedes explicarme porqué
hay que llamarla justo ahí?
Un saludo y gracias.
Vicengetorix   |194.179.126.xxx |12-03-2010 02:17:29
Ver el foro (es por no responder 2 veces)
FabianSN  - Que mala suerte!!!   |85.53.197.xxx |23-11-2011 19:18:38
Venía bien con el curso, hasta que empecé a probar los ejemplos y ahora me
encuentro con otro problema, los fps no me aumentan a más de 5.
Si, como se
lee, no más de 5 fps.
La unica forma de que aumenten es arrastrando la ventana
desde su barra de título bien abajo, que solo se vea el mensaje de FPS para que
aumente a 30.
Probé tambien el rompe ladrillos en 2D y no me anda a más de 5
fps.
Tengo una placa NVIDIA GeForce FX 5200 de 128 Mb y en mi Pc tengo 1Gb de
RAM, será que es una plataforma muy lenta? Con muchos juegos no tengo
problemas.
He probado cambiando algunas cositas y toquetee un poco el código
para que me marque el máximo FPS en algún momento de la ejecucion y he notado
gracias a eso que aumentan los FPS mientras la ventana esta parcialmente fuera
del área visible, es más, si minimizo y máximizo la ventana me muestra un
pico de FPS máximo de 999 y si oculto casi toda la ventana, dejando solo
v...
Vicengetorix   |85.53.218.xxx |21-07-2009 12:02:07
Pienso que tienes un problema con los drivers de la tarjeta. La tarjeta es mas
que suficiente para mover los programas.
Seguramente los juegos que has probado
estan hechos con DirectX.
Yo he testeado los programas en dos ATI (X550 y
mobility X600) y una Intel (no de las modernas) y funcionan con 200 FPS o mas.

Prueba el "OpenGL Extensions Viewer" para ver la capacidad de tu
tarjeta y bajate el ultimo driver.
Comentame como va.

Suerte.
FabianSN  - Son Contento     |85.53.197.xxx |23-11-2011 19:18:06
Bueno, te hice caso y me fui a buscar algún driver más actualizado.

Cambió
muchísimo, ahora estoy a 75/80 fps, creo que voy a probar cuando pueda, el
programa que me mencionas para ver la capacidad de mi tarjeta/sistema.

En
realidad los juegos comerciales no me daban problemas pero otros desarrollos en
C++ hecho por usuarios particulares como vos, esos si me daban problemas de
velocidad, aún cuando usaban DirectX.

En fin, creo que todo pasa por la
placa video/perfomance PC, pero por lo menos me haz solucionado un problema de
años en mi PC.

Ya antes había intentado incursionar en la creación de
juegos de video y los fps siempre fueron un obstaculo, ya 80 fps para mi es
suficiente para hacer muchas cosas, no obstante voy a seguir investigando si
puede aumentar aún más.

Muchas gracias maestro, me ha sido de gran ayuda.
FabianSN  - FPS   |85.53.197.xxx |23-11-2011 19:15:44
Continúo este problemita que mencione antes aquí, para no armar otro hilo en
otro lado, ya que es un problema de FPS, de lo cual habla este
articulo.

Probé el soft \"OpenGL Extensions Viewer 3.0\" e
hice un test de velocidades y me informa que hasta OpenGL 1.5 la velocidad ronda
entre 180/200 FPS,pero cuando hace el test para OpenGL 2.0 y 2.1 la velocidad
cae entre 50/70 FPS.

¿Tendrá que ver con la libreria de OpenGL que estoy
usando la cual es la última version?
¿Hay forma de que los programas los
compile para que usen opengl 1.5?
O bien, ¿hay forma de decirle que se ejecute
con opengl 1.5?

Saludos y gracias, pero no termino de entender bien entre la
libreria opengl con sus versiones, el driver nuevo que baje de NVIDIA y que
testea este soft que mencione antes.
Vicengetorix   |85.53.215.xxx |24-07-2009 11:35:18
Nos estamos adelantando al curso.
El tema de las versiones tiene que ver con las
extensiones.
De momento todo lo que estamos haciendo es con la version 1.1 de
OpenGL, aunque nuestra tarjeta grafica acepte mas.
En dos capitulos veremos
estas cosas.
La libreria que usas es la que el driver de tu tarjeta instala mas
la que viene con Windows (que es 1.1). Para usar versiones superiores o
extensiones, debes preparar tu programa a mano o con alguna libreria como
GLEE.
Por ahora no te preocupes del tema si el PC ya te va suficientemente
rapido (no solo de tarjeta grafica vive OpenGL, tambien procesador central,
memoria, ...).
Pedro  - Hola   |189.145.138.xxx |16-06-2009 22:51:51
Hola, exelentes tutoriales espero pronto subas los demas gracias.

3.26 Copyright (C) 2008 Compojoom.com / Copyright (C) 2007 Alain Georgette / Copyright (C) 2006 Frantisek Hliva. All rights reserved."

 


Banner
Spanish Chinese (Simplified) English French German Japanese Portuguese Russian