Está en la página 1de 40

Introducción a la

programación de
videojuegos
David Erosa García
Luis Rodero Morales

ascii@talika.eii.us.es tf2@talika.eii.us.es
Programación 3D

PONER ALGO
Fundamentos de OpenGL
Inicializar SDL y OpenGL

• Cabeceras: <GL/gl.h> y <GL/glu.h>

• Librerias: libGL.so y libGLU.so (linux); opengl32.lib y glu32.lib (win32)

• Para poder usar OpenGL con SDL, hay que pasar alguno de lo siguientes
FLAGS a la llamada a SDL_SetVideoMode(...):

• SDL_OPENGL

• SDL_OPENGLBLIT

• El intercambio de los buffer se realiza con:


void SDL_GL_SwapBuffers ( void );

• Para establecer algunos valores, usaremos


int SDL_GL_SetAttribute ( SDL_GLattr attr, int value );

• Nosotros solo estableceremos SDL_GL_DOUBLEBUFFER a 1.

3
Fundamentos de OpenGL
Inicialización de OpenGL 1

• Dado que OpenGL se comporta como una máquina de estados, podemos


cambiar su estado en cualquier momento durante la ejecución del programa.

• A pesar de esto, es conveniente establecer ciertos parámetros al principio


del programa.

• Iluminación.

• Función de Z-Buffer.

• Carga de texturas.

• Modelo de sombreado.

• Ocultación de caras traseras.

• ...

4
Fundamentos de OpenGL
Inicialización de OpenGL 2

glViewport (0, 0, w, h); // Tamaño de la ventana.


glMatrixMode (GL_PROJECTION); // Matriz de proyección...

glLoadIdentity (); // ... “reseteada”.


gluPerspective (60.0, (GLfloat)w / (GLfloat)h, .5f, 100.0f ); // Transformación.

glMatrixMode (GL_MODELVIEW); // Matriz de modelado...


glLoadIdentity (); // ... también “reseteada”.

SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1 ); // Doble buffer.


glClearColor (1.0, 1.0, 1.0, 0.0); // Limpia la pantalla en negro.

glShadeModel (GL_SMOOTH); // Modelo de Representación


glEnable (GL_DEPTH_TEST); // Profundidad.
glFrontFace ( GL_CCW ); // Especifica la cara frontal.

5
Fundamentos de OpenGL
Redimensionado

• En caso de que se permita el cambio de tamaño de la ventana de la


aplicación, habría que seguir los siguientes pasos:

• Volver a llamar a SDL_SetVideoMode para cambiar el tamaño de la


superficie.

• Cambiar el tamaño de la ventana con glViewport ( ... ).

• Cargar la matriz identidad en las matrices de proyección y modelado


con glLoadIdentity();

6
Fundamentos de OpenGL
TODO

• Para mandar la geometría de nuestro mundo a OpenGL existen 3 métodos:


Directo, Compilado y Arrays de Vértices (Vertex-Array).

• Antes de mandar la geometría (vértices) limpiamos los bufers de color y


profundidad con:
glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

• También es conveniente cargar la matriz identidad, en caso de no haber


guardado la matríz en pila (lo veremos más adelante) con:
glLoadIdentity ();

• Finálmente ajustamos la posición y orientación del observador con:


gluLookAt ( eye_x, eye_y, eye_z,
to_x, to_y, to_z,
up_x, up_y, up_z );

7
Fundamentos de OpenGL
Modo Directo

• Este modo manda directamente la geometría a OpenGL.

• Los datos a mandar se encuentran entre las funciones


void glBegin( GLenum modo );
y
void glEnd ( void );

• Donde modo puede ser:

• GL_POINTS

• GL_LINES, GL_LINE_STRIP, GL_LINE_LOOP

• GL_TRIANGLES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN

• GL_QUADS, GL_QUAD_STRIP

• GL_POLYGON

8
Fundamentos de OpenGL
GL_POINTS

• Especifica vértices a dibujar como puntos.

• El tamaño de los puntos se puede cambiar con


void glPointSize (GLfloat size);

• El uso es el siguiente:

glBegin ( GL_POINTS );

glVertex3f ( -1.0, -1.0, 0.0 );


glVertex3f ( 1.0, -1.0, 0.0 );

glVertex3f ( 0.0, 1.0, 0.0 );


glEnd ();

9
Fundamentos de OpenGL
GL_LINES

• Especifica vértices a usar como extremos de líneas rectas.

• El uso es el siguiente:

glBegin ( GL_LINES ); // Cada par de vértices genera una linea.


glVertex3f ( -1.0, 0.0, 0.0); // Un extremo de una linea.

glVertex3f ( 1.0, 0.0, 0.0); // El otro extremo.

glVertex3f ( 0.0, 1.0, 0.0); // Un extremo de la otra.


glVertex3f ( 0.0, -1.0, 0.0); // Final de la linea.

glEnd ();

10
Fundamentos de OpenGL
GL_LINE_STRIP - GL_LINE_LOOP

• Usan la lista de vértices para generar una sola linea quebrada.

• A diferencia de GL_LINE_STRIP, GL_LINE_LOOP une con una línea el


último vértice especificado con el primero.

11
Fundamentos de OpenGL
GL_TRIANGLES

• Por cada trío de vértices, genera un triángulo.

• Hay que tener cuidado con el sentido de creación de los vértices, pues el
sentido incorrecto puede provocar que no se visualice.

glBegin ( GL_TRIANGLES );

glVertex3f ( -1.0, -1.0, 0.0 );


glVertex3f ( 1.0, -1.0, 0.0 );
glVertex3f ( 0.0, 1.0, 0.0 );

glEnd ();

12
Fundamentos de OpenGL
GL_TRIANGLE_STRIP

• Genera una tira de triángulos de la siguiente forma:

• Primero genera un triángulo completo con los tres primeros vértices.

• A continuación, especificando solo un nuevo vértice, se usan los dos últimos


vértices de cada triángulo para generar otro:

V4

3
V2
V3
2
1

V0 V1

13
Fundamentos de OpenGL
GL_TRIANGLE_STRIP

• Genera una abanico de triángulos.

• Primero se especifica el vértice central, y a continuación el resto.

glBegin (GL_TRIANGLE_FAN);

glVertex3f (4.0, 0.0, 0.0);


for (float angulo = 0.0f; angulo < (2 * GL_PI); angulo += ( GL_PI / 9.0 ))

{
x = 4 + 2.0 * sin (angulo);

y = 2.0 * cos (angulo);


glVertex2f (x, y);

}
glEnd ();

14
Fundamentos de OpenGL
GL_QUADS - GL_QUADS_STRIP

• Estos modos generan cuadriláteros por cada cuatro vértices.

• El modo GL_QUAD_STRIP es similar a GL_TRIANGLE_STRIP, pues usa


los dos últimos vértices del anterior cuadrilátero y otros dos nuevos para
generar el siguiente.

V1 V2 V5

V0 V3 V4

15
Fundamentos de OpenGL
GL_POLYGON

• Genera polígonos de cualquier número de lados.

• Cuidado con los polígonos no convexos.

16
Fundamentos de OpenGL
Transformaciones

• Para realizar desplazamientos, rotaciones y escalados, hay que modificar la


matriz de modelado con ciertas funciones de OpenGL.

• Para conseguir el efecto de desplazamiento de los objetos:


void glTranslatef ( GLfloat x, GLfloat y, GLfloat z );

• La rotación se consigue con:


void glRotatef ( GLfloat ang, GLfloat x, GLfloat y, GLfloat z );

• ang es el ángulo a rotar alrededor del eje dado por el vector [x, y, z].

• Podemos escalar con:


void glScalef ( GLfloat x, GLfloat y, GLfloat z );

• Escala la matriz con un factor x, y, z.

17
Fundamentos de OpenGL
Listas de visualización 1

• Otro de los modos de mandar geometría a OpenGL es creando listas


de visualización.

• Estas listas son secuencias de vértices precompilados de forma que


no tienen que procesarse en cada iteración, solo llamadas.

• Suponen una mejora de rendimiento con respecto al modo directo.

18
Fundamentos de OpenGL
Listas de visualización 2

• Primero hay que reservar espacio para las listas


GLuint glGenLists ( GLsizei range );

• Esto nos devuelve un índice a partir del cual podemos numerar


nuestras listas.

• Antes de comenzar un bloque con glBegin:


void glNewList ( GLuint lista, GLenum modo );

• Con modo:

• GL_COMPILE

• GL_COMPILE_AND_EXECUTE

• La diferencia entre los dos es que el segundo representa la


geometría a la vez que la compila.

19
Fundamentos de OpenGL
Listas de visualización 3

• Tras terminar el bloque con glEnd() cerramos la lista con:


void glEndList ( void );

• Solo queda llamar a la lista cuando necesitemos renderizarla.


void glCallList ( GLuint lista );

20
Fundamentos de OpenGL
Iluminación 1

• Para construir luces en OpenGl debemos aclarar antes tres conceptos:

• Luz ambiental: Es la luz que no proviene de ninguna fuente ni


dirección en particular, pues los rebotes con el entorno le hacen
perder direccionalidad.

• Luz difusa: Es aquella que viene de una dirección particular, pero


que se refleja suavemente en una superficie, como luz fluorescente.

• Luz especular: Es también direccional, pero se refleja de forma


uniforme y precisa en las superficies, como un rayo láser.

• Toda luz tiene cierta cantidad de componente ambienta, difusa y


especular.

21
Fundamentos de OpenGL
Iluminación 2

• Antes de poder construir nuestras luces en OpenGL, hay que activar el


flag correspondiente a la iluminación:
glEnable ( GL_LIGHTNING ) ;

• Para especificar la luz ambiental, usamos


glLightModelfv ( GL_LIGHT_MODEL_AMBIENT, arrayRGBA );

• Una vez que tenemos iluminación ambiental, hay que dar propiedades
a los materiales.

• Usaremos el llamado “seguimiento de color”.


glEnable ( GL_COLOR_MATERIAL );

22
Fundamentos de OpenGL
Texturas (1)

• Antes de texturizar un objeto, hay que activar una serie de opciones en


OpenGL . Esto lo hacemos en nuestra función init().

glEnable ( GL_TEXTURE_2D )

23
Fundamentos de OpenGL
Texturas (2)

• Para aplicar una textura a un objeto, primero necesitamos crear dicha


textura. Para ésto, nos servimos de un fichero gráfico con los datos de color.

• Las texturas deben tener potencias de dos como dimensiones (128x128,


256x256, 512x512).

• Hemos de generar un espacio para la textura. Ésto se hace con la función


glGenTextures ( int , GLuint ).

• Luego especificamos el tipo de textura para dicho espacio. Usamos la


función glBindTexture ( GL_TEXTURE_2D , GLuint ).

• Finalmente generamos los datos de la textura con la función glTexImage2D


(GL_TEXTURE_2D , nivel , componentes , ancho , alto, 0,
formato , GL_UNSIGNED_BYTE, *pixels ).

24
Fundamentos de OpenGL
Texturas (3)

• Una vez creada la textura, necesitamos “pegarla” al objeto que queramos.

• Para ésto utilizamos el concepto de coordenadas de textura.

1,0
v1

v3
v2

v1
v3

v2

0,0 0,1

25
Fundamentos de OpenGL
Texturas (4)

• Para asignar coordenadas de textura a un vértice, llamamos a la función


glTexCoord2f ( GLfloat u , GLfloat v ).

• Como cada vértice tendrá sus propias coordenadas de textura, habrá que
llamar a glTexCoord2f cada vez que definamos un vértice con glVertex*.

26
Fundamentos de OpenGL
Niebla

• El efecto de niebla en OpenGL es muy sencillo, basta con activar la niebla y


especificar la densidad, color y tipo de niebla.

• La activación se realiza con:


glEnable ( GL_FOG )

• La densidad, color y tipo con:


glFogf ( GL_FOG_DENSITY, Glfloat densidad)

glFogfv (GL_FOG_COLOR, Glfloat * color)


glFogi (GL_FOG_MODE, MODO)
glFogi ( GL_FOG_START, GLfloat );
glFogi ( GL_FOG_END, GLfloat );

• Donde MODO puede ser: GL_LINEAR | GL_EXP | GL_EXP2

27
Aplicaciones
Introducción

• Ya tenemos nociones básicas de dibujo en 3D. Con ellas y utilizando


algunas técnicas podemos hacer cosas más complejas.

• Por ejemplo, podemos crear modelos tridimensionales.

• También podemos crear una cámara genérica, que tome todas sus
características como parámetros, y podamos moverla libremente por el
espacio.

• También podemos crear efectos especiales de luz y atmosféricos ( pero esto


ya empieza a tener mandanga :P ).

• Algo muy importante : que dibujemos en 3D no significa que nuestro mundo


lógico sea tridimensional.

28
Aplicaciones
Modelos 3D (1)

• En 2D, para representar objetos y personajes, usábamos Sprites.

• En 3D también podemos usar Sprites, pero lo suyo es usar modelos 3D.

• Un modelo 3D (para nosotros) es un conjunto de vértices y de triángulos.

• Un ejemplo de modelo es un cubo:

• Tiene 12 triángulos (2 triángulos por cara del cubo).

• Para dibujarlo hacemos glBegin ( GL_TRIANGLES ) 12 veces.

• Problema : un triángulo está formado por 3 vértices, 12 * 3 = 36 vértices


en total ( uf, pero un cubo no eran 8 vértices?? ).

• Solución : las caras pueden compartir vértices, definimos 8 vértices y cada


triángulo contiene 3 índices.

29
Aplicaciones
Modelos 3D (2)

• Los modelos pueden llegar a tener un número bastante alto de triángulos.

• Problema : dibujar los modelos a mano se convierte en algo incómodo


( por no decir imposible ).

• “Uf, por ahí hay gente que dibuja los modelos en el código, no es coña”
(Luis).

• Solución : crear los modelos en un modelador y desarrollar herramientas


que los importen a un formato de nuestro gusto.

• Usaremos unas estructuras de datos que tengan relación directa con


nuestras necesidades.

30
Aplicaciones
Modelos 3D (3)

• Para guardar vértices, usaremos una estructura vertex con los siguientes
campos:

• x, y, z : coordenadas espaciales del vértice

• u, v : coordenadas de textura

• Para guardar triángulos, usaremos la siguiente estructura triangle:

• v[3] : array de índices.

• Para guardar materiales, tendremos la estructura material:

• r, g, b : color del material

• textureID : id de la textura (si tiene)

31
Aplicaciones
Modelos 3D (4)

• Para almacenar una malla, tenemos la estructura mesh :

• mat_id : id del material

• n_triangles : número de triángulos

• n_vertices : número de vértices

• vertex *v_list : array de vértices

• triangle *t_list : array de triángulos

• Finalmente, para almacenar el modelo, tenemos model :

• n_mats : número de materiales

• n_meshes : número de mallas

• material *mat_list : array de materiales

• mesh *mesh_list : array de mallas

32
Aplicaciones
Modelos 3D (5)

• Necesitamos algo para convertir los datos de un formato de modelador a


nuestro formato propio.

• Tenemos una herramienta (ase2mod) que traduce los modelos exportados


en ASE de 3D Studio MAX.

• La herramienta aún está en desarrollo, por lo que ahora mismo no ofrece


una funcionalidad completa ( no carga texturas por ejemplo ).

• Nuestro formato soporta sombreado por triángulos. El sombreado por


vértices es fácil de implementar y aporta mejores resultados visuales.

33
Aplicaciones
Mapping en 3D (1)

• La técnica de mapping descrita para 2D es fácilmente practicable en 3D de


la siguiente manera:

• Tenemos un array de texturas que representarán los tiles.

• Para dibujar el mapa, aplicamos la textura que corresponda según la


matriz de mapeado en un quad y lo dibujamos en la posición que nos diga
dicha matriz.

• Una variante del método es usar modelos que representen trozos de


escenario en lugar de quads con textura.

• A pesar de todo, lo que más se utiliza para escenarios es un gran modelo


que represente la zona por la que nos vamos a mover.

34
Aplicaciones
Mapping en 3D (2)

Imágenes de Downtown Drivin'


(Monstrous Software: http://home.planet.nl/~monstrous)

35
Bibliografía

• Internet

• API's

• Página oficial de SDL : http://www.libsdl.org

• Página oficial de Allegro : http://alleg.sf.net

• Suplementos de Allegro: http://www.allegro.cc

• Página de OpenGL : http://www.opengl.org

• Desarrollo de juegos en general:

• Gamedev http://www.gamedev.net

• Flipcode http://www.flipcode.com

• GameTutorials http://www.gametutorials.com

• Monstrous Software http://home.planet.nl/~monstrous

• UGP http://www.ultimategameprogramming.com

36
Bibliografía

• Inteligencia Artificial

• AIDepot http://www.aidepot.com

• GameAI http://www.gameai.com

• Amit's Game Programming Site (pregunta, que no cabe)

• Generation5 http://www.generation5.org

• Gráficos

• NeHe http://nehe.gamedev.net

• Cone3D http://cone3d.gamedev.net

• Varios:

• Google (Dios bendiga a Google) http://www.google.com

• Code Box http://code.box.sk

37
Bibliografía

• Libros

• Game Programming Gems 1, 2, 3 y 4

• AI Game Programming Wisdom 1 y 2

• Core Techniques and Algorithms in Game Programming

• Physics for Game Developers

• Game Architecture and Design

• OpenGL Programming Guide (a.k.a. the Red Book)

• OpenGL Programming Reference (a.k.a. the Blue Book)

• ...

38
EOD && EOC

• Agradecimientos:

• Al SIC, por este pedazo de aula y de equipos (aunque exploten los


monitores...)

• A Mauri, por su portátil : http://www.laffer.tk

• A Coque, por sus gráficos (sin acritud <@:) ) .

• A Jezú, por darnos espinacas.

• Al Lidl, por sus galletas maría.

• A Sur Multimedia, por hacernos perder una tarde.

• Al UT2004.

• A ID Software, por tenernos en ascuas con el Doom 3.

• A Valve, por esperar a ID.

• A nosotros mismos.

• A AsCII.

39
P.D.

• Si a alguien le interesa (o conoce alguien que le interese) cualquier cosa


relacionada con el diseño y programación de videojuegos, con la
programación en general o con cualquier cosa, tiene algún proyecto en
mente y necesita ayuda, o le apetece ayudar en algún proyecto, que se pase
por AsCII y que nos haga saber de su existencia.

• Nuestro correo está para que nos escribáis, esaboríos:


tf2@talika.eii.us.es

40

También podría gustarte